From 771696d0ffe5cf4761ab6a3abe4cc946f3d541ff Mon Sep 17 00:00:00 2001 From: nixonwidjaja Date: Fri, 13 Oct 2023 02:49:01 +0800 Subject: [PATCH] Add leave command --- .../java/seedu/address/logic/Messages.java | 4 +- .../address/logic/commands/AddCommand.java | 2 +- .../address/logic/commands/LeaveCommand.java | 104 ++++++++++++++++++ .../logic/parser/AddCommandParser.java | 2 + .../logic/parser/AddressBookParser.java | 4 + .../seedu/address/logic/parser/CliSyntax.java | 1 + .../logic/parser/LeaveCommandParser.java | 74 +++++++++++++ .../seedu/address/model/person/Leave.java | 39 ++++++- .../java/seedu/address/ui/PersonCard.java | 3 + src/main/resources/view/PersonListCard.fxml | 1 + 10 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/main/java/seedu/address/logic/commands/LeaveCommand.java create mode 100644 src/main/java/seedu/address/logic/parser/LeaveCommandParser.java diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index 60154600561..de05fa9d061 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -14,8 +14,8 @@ 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 employee index provided is invalid"; + public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d employees listed!"; public static final String MESSAGE_DUPLICATE_FIELDS = "Multiple values specified for the " + "following single-valued field(s): "; public static final String MESSAGE_OVER_CLAIM = "Claim is REJECTED as the amount is greater than " diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index 505239c9268..337c4d69ef0 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -44,7 +44,7 @@ public class AddCommand extends Command { + PREFIX_DOB + "1999-07-23"; public static final String MESSAGE_SUCCESS = "New employee added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; + public static final String MESSAGE_DUPLICATE_PERSON = "The employee already exists in the address book"; private final Person toAdd; diff --git a/src/main/java/seedu/address/logic/commands/LeaveCommand.java b/src/main/java/seedu/address/logic/commands/LeaveCommand.java new file mode 100644 index 00000000000..eb6bd25813f --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/LeaveCommand.java @@ -0,0 +1,104 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_MONTH; +import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; + +import java.util.List; + +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.Leave; +import seedu.address.model.person.Person; + +/** + * Adds leave months for an employee. + */ +public class LeaveCommand extends Command { + + public static final String COMMAND_WORD = "leave"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds leave months for an employee.\n" + + "Parameters: INDEX (must be a positive integer) " + PREFIX_MONTH + "MONTHS\n" + + "Format: MONTHS must be integers separated by commas without spaces. " + + "1 - Jan, 2 - Feb, ..., 12 - Dec.\n" + + "Example: " + COMMAND_WORD + " 1 " + + PREFIX_MONTH + "3,-4 to add leave in March and remove leave in April."; + + public static final String MESSAGE_AMBIGUOUS = "Please check your MONTHS. Ambiguous leave(s) assignment\n"; + public static final String MESSAGE_INVALID_MONTH = "Please check your MONTHS. Invalid month provided.\n"; + public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Leave(s) successfully updated for employee: %1$s"; + public static final String MESSAGE_NOT_A_NUMBER = "Please check your MONTHS. Some is not a number.\n"; + public static final String MESSAGE_NOT_EDITED = "The employee's leave(s) does not change from previous state: %1$s"; + public static final String MESSAGE_SPACES_DETECTED = "Spaces detected in your MONTHS.\n"; + + private final Index index; + private final String change; + + /** + * Constructs a LeaveCommand to update the {@code Leave} of a {@code Person} + * with the given index. + * @param index + * @param change + */ + public LeaveCommand(Index index, String change) { + requireNonNull(index); + requireNonNull(change); + + this.index = index; + this.change = change; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + List lastShownList = model.getFilteredPersonList(); + + if (index.getZeroBased() >= lastShownList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person oldPerson = lastShownList.get(index.getZeroBased()); + Leave oldLeave = oldPerson.getLeave(); + Leave newLeave = oldLeave.update(change); + + if (oldLeave.equals(newLeave)) { + throw new CommandException(String.format(MESSAGE_NOT_EDITED, oldLeave.toString())); + } + + Person newPerson = new Person(oldPerson.getName(), oldPerson.getPhone(), oldPerson.getEmail(), + oldPerson.getAddress(), oldPerson.getSalary(), oldPerson.getClaimBudget(), + oldPerson.getDepartment(), oldPerson.getDob(), newLeave); + + model.setPerson(oldPerson, newPerson); + model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(newPerson))); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof EditCommand)) { + return false; + } + + LeaveCommand otherCommand = (LeaveCommand) other; + return index.equals(otherCommand.index) + && change.equals(otherCommand.change); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("index", index) + .add("leave", change) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 2a81e82fae7..7eecacac56d 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -1,5 +1,6 @@ package seedu.address.logic.parser; +import static java.util.Objects.requireNonNull; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; import static seedu.address.logic.parser.CliSyntax.PREFIX_CLAIM_BUDGET; @@ -34,6 +35,7 @@ public class AddCommandParser implements Parser { * @throws ParseException if the user input does not conform the expected format */ public AddCommand parse(String args) throws ParseException { + requireNonNull(args); ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_SALARY, PREFIX_CLAIM_BUDGET, PREFIX_DEPARTMENT, PREFIX_DOB); diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 392be23cb27..0dbe763661f 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -17,6 +17,7 @@ import seedu.address.logic.commands.ExitCommand; import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; +import seedu.address.logic.commands.LeaveCommand; import seedu.address.logic.commands.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; @@ -81,6 +82,9 @@ public Command parseCommand(String userInput) throws ParseException { case ClaimCommand.COMMAND_WORD: return new ClaimCommandParser().parse(arguments); + case LeaveCommand.COMMAND_WORD: + return new LeaveCommandParser().parse(arguments); + default: logger.finer("This user input caused a ParseException: " + userInput); throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index e5871c51bbc..0aa2c9843b4 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -14,6 +14,7 @@ public class CliSyntax { public static final Prefix PREFIX_CLAIM_BUDGET = new Prefix("b/"); public static final Prefix PREFIX_DEPARTMENT = new Prefix("d/"); public static final Prefix PREFIX_DOB = new Prefix("dob/"); + public static final Prefix PREFIX_MONTH = new Prefix("m/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); public static final Prefix PREFIX_CLAIM_AMOUNT = new Prefix("$/"); } diff --git a/src/main/java/seedu/address/logic/parser/LeaveCommandParser.java b/src/main/java/seedu/address/logic/parser/LeaveCommandParser.java new file mode 100644 index 00000000000..efaeed77c93 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/LeaveCommandParser.java @@ -0,0 +1,74 @@ +package seedu.address.logic.parser; + +import static java.util.Objects.requireNonNull; +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_MONTH; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.LeaveCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.person.Leave; + +/** + * Parses input arguments and creates a new LeaveCommand object + */ +public class LeaveCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the AddCommand + * and returns an AddCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public LeaveCommand parse(String args) throws ParseException { + requireNonNull(args); + System.out.println(args); + ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_MONTH); + + Index index; + try { + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + } catch (ParseException pe) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, LeaveCommand.MESSAGE_USAGE), pe); + } + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_MONTH); + if (argMultimap.getValue(PREFIX_MONTH).isPresent()) { + return new LeaveCommand(index, parseLeave(argMultimap.getValue(PREFIX_MONTH).get())); + } else { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, LeaveCommand.MESSAGE_USAGE)); + } + } + + private String parseLeave(String arg) throws ParseException { + arg = arg.trim(); + int len = arg.split("\\s+").length; + if (len > 1) { + throw new ParseException(LeaveCommand.MESSAGE_SPACES_DETECTED + LeaveCommand.MESSAGE_USAGE); + } + StringBuilder months = new StringBuilder(Leave.NO_LEAVE); + String[] args = arg.split(","); + for (int i = 0; i < args.length; i++) { + if (args[i].length() > 3) { + throw new ParseException(LeaveCommand.MESSAGE_INVALID_MONTH + LeaveCommand.MESSAGE_USAGE); + } + try { + if (args[i].charAt(0) == '-') { + Integer month = Integer.valueOf(args[i].substring(1)); + if (months.charAt(month - 1) == '+') { + throw new ParseException(LeaveCommand.MESSAGE_AMBIGUOUS + LeaveCommand.MESSAGE_USAGE); + } + months.setCharAt(month - 1, '-'); + } else { + Integer month = Integer.valueOf(args[i]); + if (months.charAt(month - 1) == '-') { + throw new ParseException(LeaveCommand.MESSAGE_AMBIGUOUS + LeaveCommand.MESSAGE_USAGE); + } + months.setCharAt(month - 1, '+'); + } + } catch (NumberFormatException e) { + throw new ParseException(LeaveCommand.MESSAGE_NOT_A_NUMBER + LeaveCommand.MESSAGE_USAGE); + } + } + return months.toString(); + } + +} diff --git a/src/main/java/seedu/address/model/person/Leave.java b/src/main/java/seedu/address/model/person/Leave.java index 6e4b5291087..42707b776f1 100644 --- a/src/main/java/seedu/address/model/person/Leave.java +++ b/src/main/java/seedu/address/model/person/Leave.java @@ -9,6 +9,9 @@ public class Leave { public static final int LEAVE_LENGTH = 12; public static final String MESSAGE_CONSTRAINTS = "Invalid leave format"; + public static final String NO_LEAVE = "000000000000"; + private static final String[] MONTHS = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; public final String leave; @@ -16,7 +19,7 @@ public class Leave { * Constructs an empty {@code Leave}. */ public Leave() { - this.leave = "000000000000"; + this.leave = NO_LEAVE; } /** @@ -40,16 +43,46 @@ public static boolean isValidLeave(String test) { return false; } for (int i = 0; i < LEAVE_LENGTH; i++) { - if (test.charAt(i) != '0' || test.charAt(i) != '1') { + if (test.charAt(i) != '0' && test.charAt(i) != '1') { return false; } } return true; } + /** + * Updates current leave. + * @param change + * @return + */ + public Leave update(String change) { + StringBuilder newLeave = new StringBuilder(leave); + for (int i = 0; i < LEAVE_LENGTH; i++) { + if (change.charAt(i) == '+') { + newLeave.setCharAt(i, '1'); + } + if (change.charAt(i) == '-') { + newLeave.setCharAt(i, '0'); + } + } + return new Leave(newLeave.toString()); + } + @Override public String toString() { - return leave; + if (leave.equals(NO_LEAVE)) { + return "-"; + } + String leaves = ""; + for (int i = 0; i < LEAVE_LENGTH; i++) { + if (leave.charAt(i) == '1') { + if (leaves.length() > 0) { + leaves += ", "; + } + leaves += MONTHS[i]; + } + } + return leaves; } @Override diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 5148a68859a..236dbbf652f 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -43,6 +43,8 @@ public class PersonCard extends UiPart { private Label department; @FXML private Label dob; + @FXML + private Label leave; /** * Creates a {@code PersonCode} with the given {@code Person} and index to display. @@ -59,5 +61,6 @@ public PersonCard(Person person, int displayedIndex) { claimBudget.setText("Claim budget: " + person.getClaimBudget().toString()); department.setText("Department: " + person.getDepartment().toString()); dob.setText("DOB: " + person.getDob().toString()); + leave.setText("Leave: " + person.getLeave().toString()); } } diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index 8c3a537d753..7d195799f9a 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -35,6 +35,7 @@