PROJECT: InsuRen


Overview

'Ren' in Mandarin translates to 'person' or 'people', and true to our name, this app is all about managing one’s network of clients in an organized, efficient and intuitive manner. InsuRen is geared to the needs of the modern Insurance salesman, but anyone whose business is their strong rapport with their clients will find this to be an indispensable tool.

Summary of contributions

  • Major enhancement: added the ability to edit client contact information and delete client contacts by name.

    • What it does: Instead of having to edit or delete contact info by using an index, you can edit and delete contacts directly using their name, provided their name is distinguishable from all other names present in InsuRen.

    • Justification: This feature improves the product significantly because normally, editing requires scrolling or using find to filter the list first. Since we don’t want the user to have to use the mouse, and we want to speed up processes, editing by name will help achieve the product’s goals.

    • Highlights: This enhancement extends the edit and delete commands and makes use of a new Predicate and PersonFinderUtil to find a Person when provided a unique identifier.

    • Credits: Nil.

  • Minor enhancement: Make the address, email and phone number fields Optional (Pull requests #16, #33).

    • What it does: Instead of requiring all fields to be filled when adding a person, which may require an Insurance Agent to fill placeholder information, she can leave several fields blank instead.

    • Justification: This feature improves the product significantly, because insurance agents do not always have all the information about their clients they need, but they may still need to keep track of them and contact them with whatever incomplete information they have. This feature thus adds a degree of freedom and ease of use to insurance agents.

  • Code contributed: [RepoSense]

  • Other contributions:

    • Project management:

      • Managed release v1.2 and v1.3.1 on GitHub

    • Enhancements to existing features:

      • Add a display for the number of people in InsuRen on the status bar (Pull request #8)

      • Change aesthetics and add text wrapping to Person Cards (Pull request #4)

    • Documentation:

      • Update the About Us page to reflect our team (Pull requests #2, #15)

      • Update the images shown on the project page (Pull requests #2, #15, #28, #56)

    • Community:

      • PRs reviewed (with non-trivial review comments): #22, #23, #40, #57, #58, #60, #71

      • Reported bugs and suggestions for other teams in the class (examples: 1, 2, 3, 4, 5)

    • Tools:

      • Get CI tools to print stack traces on failed tests (Pull request #77)

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

Editing a person : edit

Edits an existing person in InsuRen by the displayed list’s index or by an existing name.
Format: edit INDEX/EXISTING_NAME [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​

We recommend against (but do not forbid) using edit or delete (case-insensitive) as tags, as you may run into complications when using the tag edit and tag delete functionality.

Shorthand: e

  • You can edit a person by index or by name.

    • For editing 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, …​

    • For editing the person with a name matching the EXISTING_NAME, the name ​must uniquely identify a person.

      • If nobody matches the EXISTING_NAME, or there are multiple contacts matching it, InsuRen will notify you and not carry out changes.

      • You can be less specific or more specific in the existing name to identify a person, but in the case that two people have exactly the same name, you have to use the edit by index command.

  • 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.

  • e 2 n/Betsy Crower t/
    Edits the name of the 2nd person to be Betsy Crower and clears all existing tags.

  • edit John Doe p/91234567 e/johndoe@example.com
    Edits the phone number and email address of John Doe to be ​91234567​ and johndoe@example.com​ respectively, if John Doe can be uniquely identified by name in InsuRen.

  • e Johnny n/Betsy Crower
    Edits the name of Johnny to be Betsy Crower if Johnny can be uniquely identified by name in InsuRen.

Deleting a person : delete

Deletes the specified person from InsuRen by the displayed list’s index or by an existing name.
Format: delete INDEX/EXISTING_NAME

Shorthand: d

  • Deletes the person by index or by name.

    • For deleting by INDEX,

      • The index refers to the index number shown in the displayed person list.

      • The index must be a positive integer 1, 2, 3, …​

    • For deleting by EXISTING_NAME,

      • The name ​must uniquely identify a person.

      • If nobody matches the EXISTING_NAME, or there are multiple contacts matching it, InsuRen will notify you and not carry out changes.

      • You can be less specific or more specific in the existing name to identify a person, but in the case that two people have exactly the same name, you have to delete by INDEX.

Examples:

  • list
    delete 2
    Deletes the 2nd person in InsuRen.

  • find Betsy
    d 1
    Deletes the 1st person in the results of the find command.

  • delete John
    Deletes John if John can be uniquely identified by name in InsuRen.

  • d Abel Lee
    Deletes Abel Lee if Abel Lee can be uniquely identified by name in InsuRen.

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

By-Name-Commands Feature

General Current Implementation

The "by-name-commands" are extensions to the regular Commands, facilitated by classes that extend the regular Command classes. Currently implemented are the EditByNameCommand and the DeleteByNameCommand. They make use of String identifiers and the PersonFinderUtil to find the Person that the Command refers to, rather than an Index.
This allows time to be saved when trying to run a command, because instead of having to run a find or list command to display a Person, then type the command based on the Index of the list that the Person appears under, commands can be targeted swiftly and precisely. The "by-name-commands" depend on the following operation/classes:

  • PersonFinderUtil#findPerson(Model model, String personIdentifier) — Finds and returns the Person that is uniquely identified by the personIdentifier in the Model provided.

  • NameContainsAllKeywordsPredicate — Tests as true when the name of a Person matches all the keywords in the command’s arguments.

    • The PersonFinderUtil#findPerson method makes use of the NameContainsAllKeywordsPredicate, which is in contrast to the NameContainsKeywordsPredicate used in the FindCommand.

    • When editing/deleting by name, we need a more specific filter, rather than a general one. Instead of finding a Person that contains at least one identifier term in their name, the Person found must contain all identifier terms in their name.

The following sequence diagram shows how a command is generated by the AddressBookParser. When a <cmd> (edit/delete) is provided, the <cmd>CommandParser will either generate a <cmd>Command or a <cmd>ByNameCommand.

ByNameCommandSequenceDiagram
In the following section, the shorthand format _ByNameCommand and _Command when used in the same context will refer to a similar type of command, e.g. DeleteByNameCommand and DeleteCommand, but _ is general to refer to either Delete or Edit.

Design Considerations

Aspect: Whether a _ByNameCommand should Extend the Regular _Command
  • Alternative 1 (current choice): It extends the Command as shown:

ByNameCommandClassDiagram
  • Pros: Due to polymorphism, a _ByNameCommand can replace instances of _Command seamlessly in the code without having to change many parts to add this additional feature. It also makes sense, because a _ByNameCommand "is a" _Command (e.g. an EditByNameCommand is an EditCommand)

  • Cons: There is an unused field in EditCommand (index).

    • Alternative 2: Create a new _ByNameCommand, standalone from the _Command

  • Pros: Can save a bit of memory space on execution, since parts of the _Command that are not used do not provide extra baggage to the _ByNameCommand (e.g. no extra Index in the EditByNameCommand)

  • Cons: There is a need to modify more parts of the Logic component in the code base to accommodate a new command.

Aspect: When the Person is Searched/Matched
  • Alternative 1 (current choice): During the execution of execute

    • Additional details: A String personIdentifier will be stored in the command, and upon execute, a person is first matched, then the edit is carried out.

    • Pros: Execute takes in the model as an argument, making searching for a Person convenient.

    • Cons: The same _ByNameCommand executed at a different time can have a different result since it does not have a unique Person, but an identifier to find a name.

  • Alternative 2: Before creation of the command

    • Additional details: The command will have a Person

    • Pros: The command is deterministic, since it targets a unique Person.

    • Cons: Need to gain access to the model before the person can be found, which is not usually done by AddressBookParser; high level changes are necessary.

Edit By Name feature

Current Implementation

The edit by name mechanism is facilitated by the new Command, EditByNameCommand. It extends EditCommand with a "Person Identifier" String that is used in place of the Index (of a displayed list) used in the normal EditCommand. Additionally, it implements/depends on the following operations:

  • EditByNameCommand#execute() — Executes the command encapsulated by this EditByNameCommand.

Given below is an example usage scenario and how the Edit-By-Name mechanism behaves at each step.

Step 1. The user launches the application and already has at least one client’s contact in InsuRen.

EditByNameCommand1StateDiagram

Step 2. The user executes edit Alice p/91232233 to edit Alice’s phone number. However, there are more than two people with a name that matches Alice, so InsuRen notifies the user.

EditByNameCommand2StateDiagram
If a command fails its execution due to multiple or no people matching the identifier, it will not edit any contact details.

Step 3. The user uses a much more specific name identifier, edit Alice Tay Ren Ying p/91232233, but this does not match any contact, so InsuRen notifies the user.

EditByNameCommand3StateDiagram

Step 4. The user uses a name identifier that uniquely identifies one person, edit Alice Tay p/91232233. The edit command is carried out, and the contact details of the identified person are changed accordingly.

EditByNameCommand4StateDiagram

The following activity diagram summarizes what happens when a user executes the EditByNameCommand:

EditByNameCommandActivityDiagram

Delete By Name feature

Current Implementation

The delete by name mechanism is facilitated by the new Command, DeleteByNameCommand. It extends DeleteCommand with a "Person Identifier" String that is used in place of the Index (of a displayed list) used in the normal DeleteCommand. Additionally, it implements the following operations:

  • DeleteByNameCommand#execute() — Executes the command encapsulated by this DeleteByNameCommand.

Given below is an example usage scenario and how the Delete-By-Name mechanism behaves at each step.

Step 1. The user launches the application and already has at least one client’s contact in InsuRen.

DeleteByNameCommand1StateDiagram

Step 2. The user executes delete Alice to delete Alice from InsuRen. However, there are more than two people with a name that matches Alice, so InsuRen notifies the user.

DeleteByNameCommand2StateDiagram
If a command fails its execution due to multiple or no people matching the identifier, it will not delete any contact details.

Step 3. The user uses a much more specific name identifier, delete Alice Tay Ren Ying, but this does not match any contact, so InsuRen notifies the user.

DeleteByNameCommand3StateDiagram

Step 4. The user uses a name identifier that uniquely identifies one person, delete Alice Tay. The delete command is carried out, Alice Tay is removed from InsuRen’s contact list.

DeleteByNameCommand4StateDiagram

The following activity diagram summarizes what happens when a user executes the DeleteByNameCommand:

DeleteByNameCommandActivityDiagram

Use Case: Edit Clients by Name

MSS

  1. User requests to edit client, specifying the name of the client and any fields to be modified.

  2. InsuRen edits the client’s respective fields, and displays a confirmation message.

    Use case ends.

Extensions

  • 1a. The user does not include the person’s name.

    • 1a1. InsuRen shows an error message.

      Use case resumes at step 1.

  • 1b. The user does not include any field to edit.

    • 1b1. InsuRen shows an error message.

      Use case resumes at step 1.

  • 1c. There are multiple clients with the same name.

    • 1c1. InsuRen shows an error message, prompting the user to either use a more specific name, or edit by index.

      Use case resumes at step 1.

Use Case: Delete Clients by Name

MSS

  1. User requests to delete a client, specifying the name of the client.

  2. InsuRen deletes the specified client from storage, and displays a confirmation message.

    Use case ends.

Extensions

  • 1a. The user does not include the person’s name.

    • 1a1. InsuRen shows an error message.

      Use case resumes at step 1.

  • 1b. There are multiple clients with the same name.

    • 1b1. InsuRen shows an error message, prompting the user to either use a more specific name, or delete by index.

      Use case resumes at step 1.

Deleting a person

  1. Deleting a person

    1. Deleting by Index

      1. Prerequisites: List all persons using the list command. Multiple persons in the list.

      2. Test case: delete 1
        Expected: First client is deleted from the list. Details of the deleted client shown in the status message. Timestamp in the status bar is updated.

      3. Test case: delete 0
        Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.

      4. Other incorrect delete commands to try: delete, delete x (where x is larger than the list size or negative)
        Expected: Similar to previous.

    2. Deleting by Name

      1. Prerequisites: Make sure that nobody in InsuRen has the name/part of their name as Alice, Lee, Lim, Chua or Bob, then add people to the list with the names Alice Lee, Alice Chua, Alice Lim and Bob.

      2. Test case: delete Bob Expected: Bob is deleted. Details of the deleted client shown in the status message. Timestamp in the status bar is updated.

      3. Test case: delete Alice Chua Expected: Alice Chua is deleted. Details of the deleted client shown in the status message. Timestamp in the status bar is updated.

      4. Test case: delete Alice
        Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.

      5. Other incorrect delete commands to try: delete x (where x matches nobody in the list)
        Expected: Similar to previous.