forked from nus-cs2103-AY2324S1/tp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request nus-cs2103-AY2324S1#110 from garylow2001/meeting-t…
…imes Add command to delete meeting time from clients and leads
- Loading branch information
Showing
9 changed files
with
366 additions
and
5 deletions.
There are no files selected for viewing
117 changes: 117 additions & 0 deletions
117
src/main/java/seedu/address/logic/commands/DeleteMeetingCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/main/java/seedu/address/logic/parser/DeleteMeetingCommandParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
167 changes: 167 additions & 0 deletions
167
src/test/java/seedu/address/logic/commands/DeleteMeetingCommandTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.