Skip to content

Commit

Permalink
Merge pull request nus-cs2103-AY2324S1#110 from garylow2001/meeting-t…
Browse files Browse the repository at this point in the history
…imes

Add command to delete meeting time from clients and leads
  • Loading branch information
LicongHuang authored Nov 1, 2023
2 parents 6cf4dd3 + da97802 commit 1eae881
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 5 deletions.
117 changes: 117 additions & 0 deletions src/main/java/seedu/address/logic/commands/DeleteMeetingCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;

import java.util.List;
import java.util.Optional;

import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Client;
import seedu.address.model.person.Lead;
import seedu.address.model.person.Person;

/**
* Deletes a meeting identified using it's displayed index from the address book.
*/
public class DeleteMeetingCommand extends Command {

public static final String COMMAND_WORD = "deletemeeting";

public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Deletes the meeting identified by the index number used in the displayed meeting list.\n"
+ "Parameters: INDEX (must be a positive integer)\n"
+ "Example: " + COMMAND_WORD + " 1";

public static final String MESSAGE_DELETE_MEETING_SUCCESS = "Deleted Meeting: %1$s from Person %2$s";

private final Index targetIndex;

public DeleteMeetingCommand(Index targetIndex) {
this.targetIndex = targetIndex;
}

/**
* Deletes the meeting from the person.
* @param personToDeleteMeeting Person to delete meeting from.
* @return Person with meeting deleted.
*/
private static Person deleteMeeting(Person personToDeleteMeeting) {
requireNonNull(personToDeleteMeeting);
assert personToDeleteMeeting.isLead() || personToDeleteMeeting.isClient();

if (personToDeleteMeeting.getMeetingTime().isEmpty()) {
return personToDeleteMeeting;
}

Person personWithMeetingDeleted;

if (personToDeleteMeeting.isClient()) {
personWithMeetingDeleted = new Client(
personToDeleteMeeting.getName(),
personToDeleteMeeting.getPhone(),
personToDeleteMeeting.getEmail(),
personToDeleteMeeting.getAddress(),
Optional.empty(),
personToDeleteMeeting.getTags());
} else {
// If person is not Client, person is a Lead
assert personToDeleteMeeting.isLead();
Lead leadWithMeetingDeleted = (Lead) personToDeleteMeeting;
personWithMeetingDeleted = new Lead(
leadWithMeetingDeleted.getName(),
leadWithMeetingDeleted.getPhone(),
leadWithMeetingDeleted.getEmail(),
leadWithMeetingDeleted.getAddress(),
leadWithMeetingDeleted.getKeyMilestone(),
Optional.empty(),
leadWithMeetingDeleted.getTags());
}

return personWithMeetingDeleted;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
List<Person> lastShownList = model.getFilteredPersonList();

if (targetIndex.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}

Person personToDeleteMeeting = lastShownList.get(targetIndex.getZeroBased());
Person personWithMeetingDeleted = deleteMeeting(personToDeleteMeeting);
model.setPerson(personToDeleteMeeting, personWithMeetingDeleted);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
return new CommandResult(String.format(MESSAGE_DELETE_MEETING_SUCCESS,
personToDeleteMeeting.getMeetingTimeString(),
targetIndex.getOneBased()));
}

@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}

// instanceof handles nulls
if (!(other instanceof DeleteMeetingCommand)) {
return false;
}

DeleteMeetingCommand otherDeleteMeetingCommand = (DeleteMeetingCommand) other;
return targetIndex.equals(otherDeleteMeetingCommand.targetIndex);
}

@Override
public String toString() {
return new ToStringBuilder(this)
.add("targetIndex", targetIndex)
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import seedu.address.logic.commands.ConvertClientToLeadCommand;
import seedu.address.logic.commands.ConvertLeadToClientCommand;
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.DeleteMeetingCommand;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.FindCommand;
Expand Down Expand Up @@ -71,6 +72,9 @@ public Command parseCommand(String userInput) throws ParseException {
case DeleteCommand.COMMAND_WORD:
return new DeleteCommandParser().parse(arguments);

case DeleteMeetingCommand.COMMAND_WORD:
return new DeleteMeetingCommandParser().parse(arguments);

case ClearCommand.COMMAND_WORD:
return new ClearCommand();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package seedu.address.logic.parser;

import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.DeleteMeetingCommand;
import seedu.address.logic.parser.exceptions.ParseException;

/**
* Parses input arguments and creates a new DeleteMeetingCommand object
*/
public class DeleteMeetingCommandParser implements Parser<DeleteMeetingCommand> {

/**
* Parses the given {@code String} of arguments in the context of the DeleteMeetingCommand
* and returns a DeleteMeetingCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
@Override
public DeleteMeetingCommand parse(String args) throws ParseException {
try {
Index index = ParserUtil.parseIndex(args);
return new DeleteMeetingCommand(index);
} catch (ParseException pe) {
throw new ParseException(
String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteMeetingCommand.MESSAGE_USAGE), pe);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "client",
"address" : "123, Jurong West Ave 6, #08-111",
"keyMilestone": null,
"meetingTime" : null,
"meetingTime" : "12/12/2023 12:00",
"tags" : [ "friends" ]
}, {
"name" : "Benson Meier",
Expand Down Expand Up @@ -43,7 +43,7 @@
"type": "lead",
"keyMilestone": "01/12/2023",
"address" : "michegan ave",
"meetingTime" : null,
"meetingTime" : "12/12/2023 12:00",
"tags" : []
}, {
"name" : "Fiona Kunz",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package seedu.address.logic.commands;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;

import org.junit.jupiter.api.Test;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.Messages;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
import seedu.address.model.person.Person;
import seedu.address.testutil.PersonBuilder;

/**
* Contains integration tests (interaction with the Model) and unit tests for
* {@code DeleteMeetingCommand}.
*/
public class DeleteMeetingCommandTest {

private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());

@Test
public void execute_validIndexUnfilteredList_success() {
Person personToDeleteMeeting = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
Person personWithMeetingDeleted = new PersonBuilder(personToDeleteMeeting)
.withMeetingTime(null).buildClient(); // First person in typical address book without meeting time

DeleteMeetingCommand deleteMeetingCommand = new DeleteMeetingCommand(INDEX_FIRST_PERSON);

String expectedMessage = String.format(DeleteMeetingCommand.MESSAGE_DELETE_MEETING_SUCCESS,
personToDeleteMeeting.getMeetingTimeString(), INDEX_FIRST_PERSON.getOneBased());

ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
expectedModel.setPerson(personToDeleteMeeting, personWithMeetingDeleted);

assertCommandSuccess(deleteMeetingCommand, model, expectedMessage, expectedModel);
}

@Test
public void execute_invalidIndexUnfilteredList_throwsCommandException() {
Index outOfBoundIndex = Index.fromOneBased(
model.getFilteredPersonList().size() + 1); // Last person in typical address book
DeleteMeetingCommand deleteMeetingCommand = new DeleteMeetingCommand(outOfBoundIndex);

CommandTestUtil.assertCommandFailure(deleteMeetingCommand, model,
Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}

@Test
public void execute_validIndexFilteredList_success() {
showPersonAtIndex(model, INDEX_FIRST_PERSON);

Person personToDeleteMeeting = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
Person personWithMeetingDeleted = new PersonBuilder(personToDeleteMeeting)
.withMeetingTime(null).buildClient(); // First person in typical address book without meeting time

DeleteMeetingCommand deleteMeetingCommand = new DeleteMeetingCommand(INDEX_FIRST_PERSON);

String expectedMessage = String.format(DeleteMeetingCommand.MESSAGE_DELETE_MEETING_SUCCESS,
personToDeleteMeeting.getMeetingTimeString(), INDEX_FIRST_PERSON.getOneBased());

Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
expectedModel.setPerson(personToDeleteMeeting, personWithMeetingDeleted);

assertCommandSuccess(deleteMeetingCommand, model, expectedMessage, expectedModel);
}

@Test
public void execute_invalidIndexFilteredList_throwsCommandException() {
showPersonAtIndex(model, INDEX_FIRST_PERSON);

Index outOfBoundIndex = INDEX_SECOND_PERSON; // Second person in typical address book
// ensures that outOfBoundIndex is still in bounds of address book list
assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size());

DeleteMeetingCommand deleteMeetingCommand = new DeleteMeetingCommand(outOfBoundIndex);

CommandTestUtil.assertCommandFailure(deleteMeetingCommand, model,
Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}

@Test
public void deleteMeeting_personIsLead() {
Index indexFirstLead = Index.fromOneBased(5);
Person leadToDeleteMeeting = model.getFilteredPersonList().get(indexFirstLead.getZeroBased());
assertTrue(leadToDeleteMeeting.isLead());

Person leadWithMeetingDeleted = new PersonBuilder(leadToDeleteMeeting)
.withMeetingTime(null).buildLead(); // First lead in typical address book without meeting time

DeleteMeetingCommand deleteMeetingCommand = new DeleteMeetingCommand(indexFirstLead);

try {
deleteMeetingCommand.execute(model);
} catch (Exception e) {
fail();
}

Person expectedLead = model.getFilteredPersonList().get(indexFirstLead.getZeroBased());

assertTrue(expectedLead.isLead());
assertEquals(expectedLead, leadWithMeetingDeleted);
}

@Test
public void deleteMeeting_personNoMeetingTime_returnsPerson() {
Index indexPersonWithNoMeeting = Index.fromOneBased(3); // Third person in typical address book
Person personToDeleteMeeting = model.getFilteredPersonList()
.get(indexPersonWithNoMeeting.getZeroBased());

assertTrue(personToDeleteMeeting.getMeetingTime().isEmpty());

Person personWithMeetingDeleted = new PersonBuilder(personToDeleteMeeting)
.withMeetingTime(null).buildClient();
assertEquals(personToDeleteMeeting, personWithMeetingDeleted);

DeleteMeetingCommand deleteMeetingCommand = new DeleteMeetingCommand(indexPersonWithNoMeeting);

try {
deleteMeetingCommand.execute(model);
} catch (Exception e) {
fail();
}

Person expectedPerson = model.getFilteredPersonList().get(indexPersonWithNoMeeting.getZeroBased());
assertEquals(expectedPerson, personWithMeetingDeleted);
}

@Test
public void equals() {
DeleteMeetingCommand deleteMeetingFirstCommand = new DeleteMeetingCommand(INDEX_FIRST_PERSON);
DeleteMeetingCommand deleteMeetingSecondCommand = new DeleteMeetingCommand(INDEX_SECOND_PERSON);

// same object -> returns true
assertTrue(deleteMeetingFirstCommand.equals(deleteMeetingFirstCommand));

// same values -> returns true
DeleteMeetingCommand deleteMeetingFirstCommandCopy = new DeleteMeetingCommand(INDEX_FIRST_PERSON);
assertTrue(deleteMeetingFirstCommand.equals(deleteMeetingFirstCommandCopy));

// different types -> returns false
assertFalse(deleteMeetingFirstCommand.equals(1));

// null -> returns false
assertFalse(deleteMeetingFirstCommand.equals(null));

// different person -> returns false
assertFalse(deleteMeetingFirstCommand.equals(deleteMeetingSecondCommand));
}

@Test
public void toStringMethod() {
Index targetIndex = Index.fromOneBased(1);
DeleteMeetingCommand deleteMeetingCommand = new DeleteMeetingCommand(targetIndex);
String expectedString = DeleteMeetingCommand.class.getCanonicalName() + "{targetIndex=" + targetIndex + "}";
assertTrue(deleteMeetingCommand.toString().equals(expectedString));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_MEETING_TIME_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND;
Expand Down Expand Up @@ -37,7 +38,7 @@ public class EditCommandTest {

@Test
public void execute_allFieldsSpecifiedUnfilteredList_success() {
Person editedPerson = new PersonBuilder().buildClient();
Person editedPerson = new PersonBuilder().withMeetingTime(VALID_MEETING_TIME_AMY).buildClient();
EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build();
EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import seedu.address.logic.commands.AddLeadCommand;
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.DeleteMeetingCommand;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.EditCommand.EditLeadDescriptor;
import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
Expand Down Expand Up @@ -74,6 +75,14 @@ public void parseCommand_delete() throws Exception {
assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command);
}
//todo: test failed maybe because meeting time is null, should be fixed after merging master

@Test
public void parseCommand_deleteMeeting() throws Exception {
DeleteMeetingCommand command = (DeleteMeetingCommand) parser.parseCommand(
DeleteMeetingCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased());
assertEquals(new DeleteMeetingCommand(INDEX_FIRST_PERSON), command);
}

@Test
public void parseCommand_edit_withClient() throws Exception {
Client client = new PersonBuilder().buildClient();
Expand Down
Loading

0 comments on commit 1eae881

Please sign in to comment.