Skip to content

Commit

Permalink
Merge pull request AY2324S1-CS2103-F13-2#70 from sheryew/claim_improv…
Browse files Browse the repository at this point in the history
…ements

Claim improvements
  • Loading branch information
nixonwidjaja authored Oct 18, 2023
2 parents a8f1b3a + 0490528 commit 7ef9bd4
Show file tree
Hide file tree
Showing 13 changed files with 641 additions and 5 deletions.
27 changes: 27 additions & 0 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,33 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli

Use case ends.

**Use Case: Viewing Employee(s)' Attribute**

**MSS**

1. User requests to view specific attribute of employee(s).
2. HR Insight shows the specific attribute of the employee(s).
Use case ends.

**Extensions**
* 1a. User provides a false attribute (Prefix).
* 1a1. HR Insight shows an error message.
* 1a2. HR Insight shows all the attributes (Prefixes) it can display for employee(s).

Use case ends.

* 1b. User didn't provide any attribute that one wants to view.
* 1b1. HR Insight shows an error message.
* 1b2. HR Insights shows all the attributes (Prefixes) it can display for employee(s).

Use case ends.

* 1c. User provides more than 1 prefix/attribute that one wants to view.
* 1c1. HR Insight shows an error message informing user of the one attribute limit.
* 1c2. HR Insights shows all the attributes (Prefixes) it can display for employee(s).

Use case ends.

*{More to be added}*

### Non-Functional Requirements
Expand Down
17 changes: 16 additions & 1 deletion docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ HR Insight is a **desktop app for HR people, optimized for use via a Line Interf
- `delete 3` : Deletes the 3rd employee shown in the current list.

- `claim 2 $/-60` : Deducts $60 from the claims of the 2nd employee in the list.


- `view n/1,2 s/1,2` : View the name and salary of employees with list index of 1 & 2 respectively.

- `clear` : Deletes all employees from the database.

- `exit` : Exits the app.
Expand Down Expand Up @@ -202,6 +204,19 @@ Examples:
- `birthday` followed by `10` displays all employees who have their birthday in the month of October


### Viewing employee's details: `view`

Views employee(s)'s personal attribute.

Format: `view [n/INDEX] [a/INDEX] [e/INDEX] [e/INDEX] [s/INDEX] [b/INDEX] [d/INDEX] [dob/INDEX]`

- Gives an overview of employee(s)'s attributes.
- Maximum of one prefix is allowed. This means user can only view one attribute at a time.
- INDEX parameters can either be a single digit or digits separated by ",".

- Examples:
- `view` followed by `s/1,2` displays employees with list's index of 1 and 2 respective salaries.


### Saving the data

Expand Down
5 changes: 4 additions & 1 deletion src/main/java/seedu/address/logic/commands/ClaimCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
public class ClaimCommand extends Command {

public static final String COMMAND_WORD = "claim";
public static final String MESSAGE_EMPTY = "Kindly state the index and amount that the employee hopes to process!";
public static final String MESSAGE_EMPTY = "Kindly state the index and amount that the employee hopes "
+ "to process!\n" + "Parameters: INDEX (must be positive integer) $/CLAIM_AMOUNT.\n"
+ "Format: Positive CLAIM_AMOUNT indicates addition and negative indicates subtraction.\n"
+ "Example: claim 1 $/+500";
public static final String AMOUNT_EMPTY = "Kindly state the amount that the employee hopes to process!";
public static final String CLAIM_SUCCESS = "Claim has been successfully processed!\n";

Expand Down
157 changes: 157 additions & 0 deletions src/main/java/seedu/address/logic/commands/ViewCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.ViewCommandParser.ADDRESS_IDENTIFIER;
import static seedu.address.logic.parser.ViewCommandParser.BIRTHDAY;
import static seedu.address.logic.parser.ViewCommandParser.CLAIM_BUDGET;
import static seedu.address.logic.parser.ViewCommandParser.DEPARTMENT;
import static seedu.address.logic.parser.ViewCommandParser.EMAIL_IDENTIFIER;
import static seedu.address.logic.parser.ViewCommandParser.NAME_IDENTIFIER;
import static seedu.address.logic.parser.ViewCommandParser.PHONE_IDENTIFIER;
import static seedu.address.logic.parser.ViewCommandParser.SALARY_IDENTIFIER;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;

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

/**
* Returns ViewCommand Object based on what user's wants to view.
*/
public class ViewCommand extends Command {

public static final String COMMAND_WORD = "view";
public static final String WRONG_PREFIX = "Allowed Formats: n/, a/, e/, s/, b/, d/, dob/.\n"
+ "Example: view n/1,2";
public static final String EXCESS_PREFIX = "Kindly input only one prefix.\n"
+ "Allowed Format: n/, a/, e/, s/, b/, dob/.\n"
+ "Example: view n/1,2";

public final HashMap<String, List<Index>> references;

/**
* Initialises ViewCommand Object containing view operations on specific individuals.
*
* @param references HashMap object referencing view operations on Index individuals in list.
*/
public ViewCommand(HashMap<String, List<Index>> references) {
this.references = references;
}

/**
* Returns CommandResult after successfully parsing user's view commands.
*
* @param model {@code Model} which the command should operate on.
* @return CommandResult which contains string representation of person's attribute.
* @throws CommandException Exception thrown if index input from HR is beyond the pre-existing max list index.
*/
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
List<Person> lastShownList = model.getFilteredPersonList();

String finalString = "";

for (String key: references.keySet()) {
List<Index> indexList = references.get(key);
String tempStr = "You are viewing " + key + ":\n";
for (int i = 0; i < indexList.size(); i++) {
int listIndex = indexList.get(i).getZeroBased();
if (listIndex >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
Person personToEdit = lastShownList.get(indexList.get(i).getZeroBased());
HashMap<String, String> personRelevantInfo = generateArrInfo(personToEdit);
int index = indexList.get(i).getOneBased();
massAssertionFn(key);
if (Objects.equals(key, NAME_IDENTIFIER)) {
tempStr += String.format("%s. %s.\n", index, personRelevantInfo.get(NAME_IDENTIFIER));
} else if (Objects.equals(key, PHONE_IDENTIFIER)) {
tempStr += generateNiceStr(personRelevantInfo, index, PHONE_IDENTIFIER);
} else if (Objects.equals(key, EMAIL_IDENTIFIER)) {
tempStr += generateNiceStr(personRelevantInfo, index, EMAIL_IDENTIFIER);
} else if (Objects.equals(key, ADDRESS_IDENTIFIER)) {
tempStr += generateNiceStr(personRelevantInfo, index, ADDRESS_IDENTIFIER);
} else if (Objects.equals(key, SALARY_IDENTIFIER)) {
tempStr += generateNiceStr(personRelevantInfo, index, SALARY_IDENTIFIER);
} else if (Objects.equals(key, CLAIM_BUDGET)) {
tempStr += generateNiceStr(personRelevantInfo, index, CLAIM_BUDGET);
} else if (Objects.equals(key, DEPARTMENT)) {
tempStr += generateNiceStr(personRelevantInfo, index, DEPARTMENT);
} else {
tempStr += generateNiceStr(personRelevantInfo, index, BIRTHDAY);
}
}
finalString += tempStr + "\n";
}
return new CommandResult(finalString);
}

/**
* Assertion test to ensure key corresponds to all the existing identifiers.
*
* @param key User Input of the prefixes one wants to view.
*/
public void massAssertionFn(String key) {
assert Objects.equals(key, NAME_IDENTIFIER) || Objects.equals(key, PHONE_IDENTIFIER)
|| Objects.equals(key, EMAIL_IDENTIFIER) || Objects.equals(key, ADDRESS_IDENTIFIER)
|| Objects.equals(key, SALARY_IDENTIFIER) || Objects.equals(key, CLAIM_BUDGET)
|| Objects.equals(key, DEPARTMENT) || Objects.equals(key, BIRTHDAY);
}

/**
* Returns HashMap which contains employee's information.
*
* @param person Person object that we want to retrieve information from.
* @return HashMap, which informs us of the person's primary attributes.
*/
private HashMap<String, String> generateArrInfo(Person person) {
HashMap<String, String> map = new HashMap<>();
map.put(NAME_IDENTIFIER, person.getName().toString());
map.put(PHONE_IDENTIFIER, person.getPhone().toString());
map.put(EMAIL_IDENTIFIER, person.getEmail().toString());
map.put(ADDRESS_IDENTIFIER, person.getAddress().toString());
map.put(SALARY_IDENTIFIER, person.getSalary().toString());
map.put(CLAIM_BUDGET, person.getClaimBudget().toString());
map.put(DEPARTMENT, person.getDepartment().toString());
map.put(BIRTHDAY, person.getDob().toString());
return map;
}

/**
* Returns String containing relevant person's information.
*
* @param personInfo HashMap containing Person's primary attributes.
* @param index Integer which represents index from list.
* @param identifier String which represents what attribute to view from.
* @return String representation of relevant information.
*/
public String generateNiceStr(HashMap<String, String> personInfo, int index, String identifier) {
String result = personInfo.get(identifier);
String name = personInfo.get(NAME_IDENTIFIER);
return String.format("%s. %s's %s is %s.\n", index, name, identifier, result);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ViewCommand that = (ViewCommand) o;
return references.equals(that.references);
}

@Override
public int hashCode() {
return Objects.hash(references);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.LeaveCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.ViewCommand;
import seedu.address.logic.parser.exceptions.ParseException;

/**
Expand Down Expand Up @@ -54,7 +55,6 @@ public Command parseCommand(String userInput) throws ParseException {
logger.fine("Command word: " + commandWord + "; Arguments: " + arguments);

switch (commandWord) {

case AddCommand.COMMAND_WORD:
return new AddCommandParser().parse(arguments);

Expand Down Expand Up @@ -85,6 +85,9 @@ public Command parseCommand(String userInput) throws ParseException {
case LeaveCommand.COMMAND_WORD:
return new LeaveCommandParser().parse(arguments);

case ViewCommand.COMMAND_WORD:
return new ViewCommandParser().parse(arguments);

default:
logger.finer("This user input caused a ParseException: " + userInput);
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/seedu/address/logic/parser/ArgumentMultimap.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,19 @@ public void verifyNoDuplicatePrefixesFor(Prefix... prefixes) throws ParseExcepti
throw new ParseException(Messages.getErrorMessageForDuplicatePrefixes(duplicatedPrefixes));
}
}

/**
* Returns the list of Prefixes from the argMultimap object.
*
* @return List parsed from argMultimap object.
*/
public List<Prefix> userPrefixes() {
List<Prefix> userInputPrefixes = new ArrayList<>();
for (Map.Entry<Prefix, List<String>> entry : argMultimap.entrySet()) {
if (!entry.getKey().toString().isEmpty()) {
userInputPrefixes.add(entry.getKey());
}
}
return userInputPrefixes;
}
}
44 changes: 44 additions & 0 deletions src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import seedu.address.logic.parser.exceptions.ParseException;

/**
* Tokenizes arguments string of the form: {@code preamble <prefix>value <prefix>value ...}<br>
* e.g. {@code some preamble text t/ 11.00 t/12.00 k/ m/ July} where prefixes are {@code t/ k/ m/}.<br>
Expand Down Expand Up @@ -145,4 +151,42 @@ Prefix getPrefix() {
}
}

/**
* Returns List containing user's prefixes.
* This function is required since user's can chain prefixes for view.
*
* @param argsString Input arguments.
* @return List containing user's prefixes.
*/
private static List<String> extractPrefixes(String argsString) {
Pattern pattern = Pattern.compile("\\b[^\\s]+/");
Matcher matcher = pattern.matcher(argsString);
List<String> prefixes = new ArrayList<>();
while (matcher.find()) {
prefixes.add(matcher.group().trim());
}
System.out.println(prefixes);
return prefixes;
}

/**
* Returns ArgumentMultimap object
* Converts user's chained prefixes into a list.
*
* @param argsString User's input.
* @return ArgumentMultimap object.
* @throws ParseException if duplicate prefixes are found.
*/
public static ArgumentMultimap viewTokenize(String argsString) throws ParseException {
List<String> extractedPrefixes = extractPrefixes(argsString);

Set<String> uniquePrefixes = new HashSet<>(extractedPrefixes);
assert(uniquePrefixes.size() == extractedPrefixes.size());
if (uniquePrefixes.size() != extractedPrefixes.size()) {
throw new ParseException("Duplicate prefix detected in input.");
}
Prefix[] prefixArray = extractedPrefixes.stream().map(Prefix::new).toArray(Prefix[]::new);
List<PrefixPosition> positions = findAllPrefixPositions(argsString, prefixArray);
return extractArguments(argsString, positions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public ClaimCommand parse(String args) throws ParseException {
}

if (argMultimap.getValue(PREFIX_CLAIM_AMOUNT).isPresent()) {
String claimAmt = argMultimap.getValue(PREFIX_CLAIM_AMOUNT).get().substring(1);
if (claimAmt.length() > 6) {
throw new ParseException("Please input claim amount in the range of 0 to 100000 dollars.");
}
claim = ParserUtil.parseClaim(argMultimap.getValue(PREFIX_CLAIM_AMOUNT).get());
} else {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ClaimCommand.AMOUNT_EMPTY));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public class LeaveCommandParser implements Parser<LeaveCommand> {
*/
public LeaveCommand parse(String args) throws ParseException {
requireNonNull(args);
System.out.println(args);
ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_MONTH);

Index index;
Expand Down
Loading

0 comments on commit 7ef9bd4

Please sign in to comment.