From ec2ab77267765d513293e9b7afddd1181c741e28 Mon Sep 17 00:00:00 2001 From: chydarren Date: Mon, 31 Oct 2022 21:09:51 +0800 Subject: [PATCH] Add ability to list transactions for last N days and add spending habit message to time insights list --- src/main/java/seedu/duke/Ui.java | 7 +- .../java/seedu/duke/command/StatsCommand.java | 32 ++-- .../java/seedu/duke/common/Constants.java | 6 +- .../java/seedu/duke/common/InfoMessages.java | 7 +- .../java/seedu/duke/data/TransactionList.java | 156 ++++++++++++------ .../seedu/duke/parser/ParameterParser.java | 11 +- 6 files changed, 146 insertions(+), 73 deletions(-) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 51ee9c5ff..3a0f13b20 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -136,12 +136,15 @@ public static void showTimeInsightsList(String list, String message, String inco * @param incomeMessage A string containing the formatted income amount. * @param expenseMessage A string containing the formatted expense amount. * @param savingsMessage A string containing the formatted savings amount. + * @param spendingHabitComment A string containing the formatted spending habit comment. * @param budgetMessage A string containing the formatted budget amount. * @param budgetAdvice A string containing the formatted budget advice. */ public static void showTimeInsightsList(String list, String message, String incomeMessage, - String expenseMessage, String savingsMessage, String budgetMessage, String budgetAdvice) { - printMessages(message, list, incomeMessage, expenseMessage, savingsMessage, budgetMessage, budgetAdvice); + String expenseMessage, String savingsMessage, String budgetMessage, String spendingHabitComment, + String budgetAdvice) { + printMessages(message, list, incomeMessage, expenseMessage, savingsMessage, budgetMessage, + spendingHabitComment, budgetAdvice); } //@@author chydarren diff --git a/src/main/java/seedu/duke/command/StatsCommand.java b/src/main/java/seedu/duke/command/StatsCommand.java index 3bf41a440..bc2a8afdd 100644 --- a/src/main/java/seedu/duke/command/StatsCommand.java +++ b/src/main/java/seedu/duke/command/StatsCommand.java @@ -34,6 +34,7 @@ import static seedu.duke.common.InfoMessages.INFO_INCOME; import static seedu.duke.common.InfoMessages.INFO_SAVINGS; import static seedu.duke.common.InfoMessages.INFO_BUDGET; +import static seedu.duke.common.InfoMessages.INFO_SPENDING_HABIT; import static seedu.duke.common.InfoMessages.INFO_STATS_CATEGORY; import static seedu.duke.common.InfoMessages.INFO_STATS_EMPTY; import static seedu.duke.common.InfoMessages.INFO_STATS_EXPENDITURE_HEADER; @@ -200,33 +201,40 @@ public void statsTypeCategoricalSavingsOrMonthlyExpenditure(TransactionList tran * Produces info strings, list of categories and summary statistics. * * @param transactions An instance of the TransactionList class. + * @param ui An instance of the Ui class. */ - public void statsTypeTimeInsights(TransactionList transactions) { + public void statsTypeTimeInsights(TransactionList transactions, Ui ui) { ArrayList timeTransactions = getTimeTransactions(transactions); String timeInsightsList = transactions.listTimeStats(timeTransactions, year, month, period, number); if (timeInsightsList.isEmpty()) { statsLogger.log(Level.INFO, "Time insights list is empty as there are no transactions available."); - Ui.showInfoMessage(INFO_STATS_EMPTY.toString()); + ui.showInfoMessage(INFO_STATS_EMPTY.toString()); return; } // summary values - ArrayList amounts; - amounts = transactions.processTimeSummaryStats(timeTransactions); + ArrayList timeInsightsValues; + timeInsightsValues = transactions.processTimeSummaryStats(timeTransactions); String incomeMessage = INFO_STATS_EXPENDITURE_HEADER + LINE_SEPARATOR.toString() - + String.format("%s%s%s", INFO_INCOME, COLON_SPACE, DOLLAR_SIGN) + amounts.get(0); - String expensesMessage = String.format("%s%s%s", INFO_EXPENSE, COLON_SPACE, DOLLAR_SIGN) + amounts.get(1); - String savingsMessage = String.format("%s%s%s", INFO_SAVINGS, COLON_SPACE, DOLLAR_SIGN) + amounts.get(2); + + String.format("%s%s%s", INFO_INCOME, COLON_SPACE, DOLLAR_SIGN) + timeInsightsValues.get(0); + String expensesMessage = String.format("%s%s%s", INFO_EXPENSE, COLON_SPACE, DOLLAR_SIGN) + + timeInsightsValues.get(1); + String savingsMessage = String.format("%s%s%s", INFO_SAVINGS, COLON_SPACE, DOLLAR_SIGN) + + timeInsightsValues.get(2); + String habitMessage = String.format("%s%s%s", INFO_SPENDING_HABIT, COLON_SPACE, timeInsightsValues.get(3)); - printTimeInsightsStatistics(timeInsightsList, amounts, incomeMessage, expensesMessage, savingsMessage); + printTimeInsightsStatistics(timeInsightsList, timeInsightsValues, incomeMessage, expensesMessage, + savingsMessage, habitMessage); assert !timeInsightsList.isEmpty(); statsLogger.log(Level.INFO, "Time insights list has info available for the specified time period."); } + //@@author wcwy + /** * Prints the statistics for time insights based on the parameters chosen. * @@ -237,19 +245,19 @@ public void statsTypeTimeInsights(TransactionList transactions) { * @param savingsMessage A string containing the formatted savings. */ private static void printTimeInsightsStatistics(String timeInsightsList, ArrayList amounts, - String incomeMessage, String expensesMessage, String savingsMessage) { + String incomeMessage, String expensesMessage, String savingsMessage, String spendingHabitComment) { if (containMonthYear() == CONTAIN_BOTH) { - // Information on budget is only displayed when displaying a specific month's time insights + // Information on spending habit and budget displayed only when displaying a specific month's time insights String budgetMessage = String.format("%s%s%s", INFO_BUDGET, COLON_SPACE, DOLLAR_SIGN) + Budget.getBudget(); long budgetLeft = Budget.calculateBudgetLeft(Long.parseLong(amounts.get(1))); String budgetAdvice = Budget.generateBudgetAdvice(budgetLeft, Budget.hasExceededBudget(budgetLeft)); Ui.showTimeInsightsList(timeInsightsList, INFO_STATS_TIME_INSIGHTS.toString(), incomeMessage, - expensesMessage, savingsMessage, budgetMessage, budgetAdvice); + expensesMessage, savingsMessage, budgetMessage, spendingHabitComment, budgetAdvice); + //@@author paullowse } else { - //@@author paullowse Ui.showTimeInsightsList(timeInsightsList, INFO_STATS_TIME_INSIGHTS.toString(), incomeMessage, expensesMessage, savingsMessage); } diff --git a/src/main/java/seedu/duke/common/Constants.java b/src/main/java/seedu/duke/common/Constants.java index 8733e0d69..7a97ae518 100644 --- a/src/main/java/seedu/duke/common/Constants.java +++ b/src/main/java/seedu/duke/common/Constants.java @@ -16,7 +16,6 @@ public class Constants { public static final int MAXIMUM_STATS_NUMBER = 100; public static final int MINIMUM_STATS_NUMBER = 1; - //@@author wcwy /* @@ -28,6 +27,11 @@ public class Constants { // One million transactions is the capacity allowed public static int MAX_TRANSACTIONS_COUNT = 1000000; + //@@author chydarren + + // An amount that has no value in it + public static int NO_AMOUNT_VALUE = 0; + //@@author chinhan99 // The amount of one transaction is allowed to be in the range of 1 <= x <= 10000000 diff --git a/src/main/java/seedu/duke/common/InfoMessages.java b/src/main/java/seedu/duke/common/InfoMessages.java index 3330fb8e3..51f306d14 100644 --- a/src/main/java/seedu/duke/common/InfoMessages.java +++ b/src/main/java/seedu/duke/common/InfoMessages.java @@ -14,6 +14,7 @@ public enum InfoMessages { INFO_EXPENSE("Expense"), INFO_SAVINGS("Savings"), INFO_BUDGET("Budget"), + INFO_SPENDING_HABIT("Spending Habit"), INFO_DIVIDER("____________________________________________________________"), INFO_ADD_EXPENSE("I have added the following Expense transaction:"), INFO_ADD_INCOME("I have added the following Income transaction:"), @@ -27,17 +28,17 @@ public enum InfoMessages { INFO_LIST("Here are your transaction records:"), INFO_LIST_EMPTY("There are no transaction records found."), INFO_LIST_FILTERED("Here are the transaction records that match your search expression:"), - INFO_LIST_UNFILTERED("There are no transaction records that match your search expression."), + INFO_LIST_FILTERED_EMPTY("There are no transaction records that match your search expression."), INFO_STATS_EMPTY("There are no statistics available yet for the given statistics type."), INFO_STATS_CATEGORY("Here are your net categorical savings:"), - INFO_STATS_MONTHLY("Here are your requested monthly statistics:"), + INFO_STATS_MONTHLY("Here is a summary of your monthly expenditure:"), INFO_STATS_HABIT_VERY_HIGH_SAVINGS("Excellent! You saved quite a lot this month."), INFO_STATS_HABIT_HIGH_SAVINGS("Wow, keep up the good work. You saved at least two-third of your income."), INFO_STATS_HABIT_MEDIUM_SAVINGS("Good effort, you saved at least half of your income."), INFO_STATS_HABIT_LOW_SAVINGS("Hmm, you are spending more than 50% of what you earned. " + "Do strike a balance between what you earn and what you spend for better savings!"), INFO_STATS_HABIT_VERY_LOW_SAVINGS("You spent way more than what you have earned for the current month. " - + "Please spend wisely based on your income"), + + "Please spend wisely based on your income."), INFO_STATS_TIME_INSIGHTS("Here are the categorical savings and expenditure summary for"), INFO_STATS_CATEGORIES_HEADER("-----Categorical Savings-----"), INFO_STATS_EXPENDITURE_HEADER("-----Expenditure Summary-----"), diff --git a/src/main/java/seedu/duke/data/TransactionList.java b/src/main/java/seedu/duke/data/TransactionList.java index cc22e2178..3ec8f15f4 100644 --- a/src/main/java/seedu/duke/data/TransactionList.java +++ b/src/main/java/seedu/duke/data/TransactionList.java @@ -13,6 +13,7 @@ import java.util.HashMap; import java.util.stream.Collectors; +import static seedu.duke.common.Constants.NO_AMOUNT_VALUE; import static seedu.duke.common.Constants.MAX_AMOUNT_VALUE; import static seedu.duke.common.Constants.MIN_AMOUNT_VALUE; import static seedu.duke.common.Constants.MAX_TRANSACTIONS_COUNT; @@ -24,6 +25,7 @@ import static seedu.duke.common.InfoMessages.INFO_EXPENSE; import static seedu.duke.common.InfoMessages.INFO_SAVINGS; import static seedu.duke.common.InfoMessages.INFO_BUDGET; +import static seedu.duke.common.InfoMessages.INFO_SPENDING_HABIT; import static seedu.duke.common.InfoMessages.INFO_STATS_CATEGORIES_HEADER; import static seedu.duke.common.InfoMessages.INFO_STATS_HABIT_VERY_LOW_SAVINGS; import static seedu.duke.common.InfoMessages.INFO_STATS_HABIT_LOW_SAVINGS; @@ -31,7 +33,6 @@ import static seedu.duke.common.InfoMessages.INFO_STATS_HABIT_HIGH_SAVINGS; import static seedu.duke.common.InfoMessages.INFO_STATS_HABIT_VERY_HIGH_SAVINGS; - //@@author chydarren /** @@ -45,13 +46,21 @@ public class TransactionList { private static final String POSTFIX_CATEGORY = "]"; private static final String INCOME = "income"; private static final String EXPENSE = "expense"; - private static final int INITIAL_AMOUNT = 0; - private static final int HUNDRED_PERCENT = 100; - private static final int SEVENTY_FIVE_PERCENT = 75; - private static final int FIFTY_PERCENT = 50; - private static final int TWENTY_FIVE_PERCENT = 25; - private static final int START = 0; - private static final int END = 1; + private static final int VERY_HIGH_SAVINGS_RATE = 100; + private static final int HIGH_SAVINGS_RATE = 75; + private static final int MEDIUM_SAVINGS_RATE = 50; + private static final int LOW_SAVINGS_RATE = 25; + private static final int INDEX_FOR_START_DATE = 0; + private static final int STARTING_INDEX = 0; + private static final int INDEX_FOR_END_DATE = 1; + private static final int INDEX_FOR_INCOME = 0; + private static final int INDEX_FOR_EXPENSE = 1; + private static final int INDEX_FOR_SAVINGS = 2; + private static final int ONE_DAY = 1; + private static final int ONE_MONTH = 1; + private static final int NUMBER_OF_DAYS_IN_A_WEEK = 7; + private static final int NUMBER_OF_ACCOUNT_TYPES = 3; + private static final int NEGATE_AMOUNT = -1; private static final int UNDEFINED_PARAMETER = -1; //@@author chinhan99 @@ -247,26 +256,31 @@ public String findTransactions(String keywords) { /** * Reads the transactions list and adds each amount to the categories in categorical savings hashmap. * + * @param timeTransactions An array list of time-filtered transactions. * @param categoricalSavings A hashmap containing all category-amount pair for total savings. * @return A hashmap containing all category-amount pair for total savings. */ public HashMap processCategoricalSavings(ArrayList timeTransactions, HashMap categoricalSavings) { for (Transaction transaction : timeTransactions) { + // Category will be used as a key for the hashmap String category = transaction.getCategory(); + + // Negates the amount if transaction is an Expense int amount = transaction.getAmount(); - String type = transaction.getType(); + + if (transaction instanceof Expense) { + amount *= NEGATE_AMOUNT; + } // Creates a new category with starter amount if category not exists in hashmap - if (!categoricalSavings.containsKey(category) && type == EXPENSE) { - categoricalSavings.put(category, amount * -1); - } else if (!categoricalSavings.containsKey(category) && type == INCOME) { + if (!categoricalSavings.containsKey(category)) { categoricalSavings.put(category, amount); - } else if (type == EXPENSE) { - categoricalSavings.put(category, categoricalSavings.get(category) - amount); - } else { - categoricalSavings.put(category, categoricalSavings.get(category) + amount); + continue; } + + // Adds amount to existing category in hashmap + categoricalSavings.put(category, categoricalSavings.get(category) + amount); } return categoricalSavings; @@ -275,7 +289,7 @@ public HashMap processCategoricalSavings(ArrayList /** * Formats the hashmap of categorical savings into a categorical savings list, using timeTransactions. * - * @param timeTransactions An arraylist of transactions. + * @param timeTransactions An array list of time-filtered transactions. * @return A string that represents the formatted categorical savings list. */ public String listCategoricalSavings(ArrayList timeTransactions) { @@ -301,11 +315,13 @@ public String listCategoricalSavings(ArrayList timeTransactions) { */ public HashMap processMonthlyExpenditure(HashMap monthlyExpenditure) { for (Transaction transaction : transactions) { + // Month of date will be used as a key for the hashmap String date = transaction.getDate().format(DateTimeFormatter.ofPattern(DATE_MONTH_PATTERN.toString())); - int income = INITIAL_AMOUNT; - int expense = INITIAL_AMOUNT; - // Checks whether transaction is Income or Expense and places in respective amount + // Checks whether transaction is Income or Expense and places in respective amount type + int income = NO_AMOUNT_VALUE; + int expense = NO_AMOUNT_VALUE; + if (transaction instanceof Income) { income = transaction.getAmount(); } else { @@ -319,8 +335,8 @@ public HashMap processMonthlyExpenditure(HashMap m } // Adds amounts to existing month and year in hashmap - int updatedIncome = monthlyExpenditure.get(date)[0] + income; - int updatedExpense = monthlyExpenditure.get(date)[1] + expense; + int updatedIncome = monthlyExpenditure.get(date)[INDEX_FOR_INCOME] + income; + int updatedExpense = monthlyExpenditure.get(date)[INDEX_FOR_EXPENSE] + expense; monthlyExpenditure.put(date, new int[]{updatedIncome, updatedExpense, updatedIncome - updatedExpense}); } @@ -337,15 +353,16 @@ public HashMap processMonthlyExpenditure(HashMap m */ public String getSpendingHabitComment(int income, int savings) { if (income >= MIN_AMOUNT_VALUE) { - int savingsPercentage = HUNDRED_PERCENT * savings / income; + // Computes savingsPercentage only when savings are divisible by income, i.e. income is not 0 + int savingsPercentage = VERY_HIGH_SAVINGS_RATE * savings / income; - if (savingsPercentage >= HUNDRED_PERCENT) { + if (savingsPercentage >= VERY_HIGH_SAVINGS_RATE) { return INFO_STATS_HABIT_VERY_HIGH_SAVINGS.toString(); - } else if (savingsPercentage >= SEVENTY_FIVE_PERCENT) { + } else if (savingsPercentage >= HIGH_SAVINGS_RATE) { return INFO_STATS_HABIT_HIGH_SAVINGS.toString(); - } else if (savingsPercentage >= FIFTY_PERCENT) { + } else if (savingsPercentage >= MEDIUM_SAVINGS_RATE) { return INFO_STATS_HABIT_MEDIUM_SAVINGS.toString(); - } else if (savingsPercentage >= TWENTY_FIVE_PERCENT) { + } else if (savingsPercentage >= LOW_SAVINGS_RATE) { return INFO_STATS_HABIT_LOW_SAVINGS.toString(); } } @@ -363,25 +380,36 @@ public String listMonthlyExpenditure() { // Adds each amount from transactions list to the month and year in monthly expenditure hashmap monthlyExpenditure = processMonthlyExpenditure(monthlyExpenditure); - // Formats every entry in the hashmap into a monthly expenditure summary list + // Formats every entry in the hashmap into a monthly expenditure list for (HashMap.Entry entry : monthlyExpenditure.entrySet()) { monthlyExpenditureList += String.format("%s%s%s%s", PREFIX_CATEGORY, entry.getKey(), POSTFIX_CATEGORY, LINE_SEPARATOR); - monthlyExpenditureList += String.format("%s%s%s%s%s", INFO_INCOME, COLON_SPACE, DOLLAR_SIGN, - entry.getValue()[0], LINE_SEPARATOR); - monthlyExpenditureList += String.format("%s%s%s%s%s", INFO_EXPENSE, COLON_SPACE, DOLLAR_SIGN, - entry.getValue()[1], LINE_SEPARATOR); - monthlyExpenditureList += String.format("%s%s%s%s%s", INFO_SAVINGS, COLON_SPACE, DOLLAR_SIGN, - entry.getValue()[2], LINE_SEPARATOR); + + // Puts income, expense, savings values into monthly expenditure list + Enum[] accountType = {INFO_INCOME, INFO_EXPENSE, INFO_SAVINGS}; + for (int i = STARTING_INDEX; i < NUMBER_OF_ACCOUNT_TYPES; i++) { + monthlyExpenditureList += String.format("%s%s%s%s%s", accountType[i], COLON_SPACE, DOLLAR_SIGN, + entry.getValue()[i], LINE_SEPARATOR); + } + + // Puts monthly budget value into monthly expenditure list monthlyExpenditureList += String.format("%s%s%s%s%s", INFO_BUDGET, COLON_SPACE, DOLLAR_SIGN, Budget.getBudget(), LINE_SEPARATOR); - monthlyExpenditureList += String.format("%s%s%s", "Spending Habit: ", - getSpendingHabitComment(entry.getValue()[2], entry.getValue()[0]), LINE_SEPARATOR); + + + // Puts spending habit comment into monthly expenditure list + monthlyExpenditureList += String.format("%s%s%s%s", INFO_SPENDING_HABIT, COLON_SPACE, + getSpendingHabitComment(entry.getValue()[INDEX_FOR_INCOME], entry.getValue()[INDEX_FOR_SAVINGS]), + LINE_SEPARATOR); + + //@@author wcwy // Information on budget is only displayed when displaying a specific month's time insights long budgetLeft = Budget.calculateBudgetLeft(entry.getValue()[1]); String budgetAdvice = Budget.generateBudgetAdvice(budgetLeft, Budget.hasExceededBudget(budgetLeft)); monthlyExpenditureList += String.format("%s%s%s", budgetAdvice, LINE_SEPARATOR, LINE_SEPARATOR); + + //@@author chydarren } return monthlyExpenditureList; @@ -392,7 +420,7 @@ public String listMonthlyExpenditure() { /** * Produces Categorical saving list for timeTransactions. * - * @param timeTransactions An instance of the TransactionList class. + * @param timeTransactions An array list of time-filtered transactions. * @param year A specified year. * @param month A specified month. * @param period A specified period of time. @@ -404,7 +432,7 @@ public String listTimeStats(ArrayList timeTransactions, int year, i String timeInsightsList = ""; if (period != null && number != UNDEFINED_PARAMETER) { - timeInsightsList += "The past " + number + " " + period + ": " + LINE_SEPARATOR + LINE_SEPARATOR + timeInsightsList += "The past " + number + " " + period + ":" + LINE_SEPARATOR + LINE_SEPARATOR + INFO_STATS_CATEGORIES_HEADER + LINE_SEPARATOR; } else if (month == UNDEFINED_PARAMETER) { timeInsightsList += "Year: " + year + LINE_SEPARATOR + LINE_SEPARATOR + INFO_STATS_CATEGORIES_HEADER @@ -423,12 +451,12 @@ public String listTimeStats(ArrayList timeTransactions, int year, i /** * Produces Expense, Income and Savings statistics. * - * @param timeTransactions An instance of the TransactionList class. + * @param timeTransactions An array list of time-filtered transactions. * @return An amount arraylist of Expense and Income. */ public ArrayList processTimeSummaryStats(ArrayList timeTransactions) { - int timeExpense = INITIAL_AMOUNT; - int timeIncome = INITIAL_AMOUNT; + int timeExpense = NO_AMOUNT_VALUE; + int timeIncome = NO_AMOUNT_VALUE; for (Transaction entry : timeTransactions) { String category = entry.getType(); if (category.equals(EXPENSE)) { @@ -439,15 +467,40 @@ public ArrayList processTimeSummaryStats(ArrayList timeTran } int timeSavings = timeIncome - timeExpense; - ArrayList amounts = new ArrayList(); - amounts.add(Integer.toString(timeIncome)); - amounts.add(Integer.toString(timeExpense)); - amounts.add(Integer.toString(timeSavings)); - return amounts; + ArrayList timeInsightsValues = new ArrayList(); + timeInsightsValues.add(Integer.toString(timeIncome)); + timeInsightsValues.add(Integer.toString(timeExpense)); + timeInsightsValues.add(Integer.toString(timeSavings)); + + if (timeExpense != NO_AMOUNT_VALUE) { + timeInsightsValues.add(getSpendingHabitComment(timeIncome, timeSavings)); + } else { + timeInsightsValues.add("There is no spending habit available for this month."); + } + + return timeInsightsValues; } //@@author chydarren + /** + * Gets all transactions recorded in between specified dates, backdated from given date. + * E.g. If the date is 21 October 2022 to backdate 3 days, the range will be 17 October to 20 October 2022. + * + * @param date A specified date to backdate N days from occurring date. + * @param numberOfDays N number of days to backdate, must be minimum 1 day. + * @return An array list containing all transactions recorded in specified days. + */ + public static ArrayList getTransactionsByDayRange(LocalDate date, int numberOfDays) { + ArrayList transactionsByDayRange = new ArrayList<>(); + + LocalDate from = date.minusDays(numberOfDays); + LocalDate to = date.minusDays(ONE_DAY); + + transactionsByDayRange = getTransactionsByDateRange(new LocalDate[]{from, to}, transactionsByDayRange); + return transactionsByDayRange; + } + /** * Gets all transactions recorded in between specified weeks, backdated from given date. * E.g. If the date is 21 October 2022 to backdate 2 weeks, the range will be 3 October to 16 October 2022. @@ -462,7 +515,8 @@ public static ArrayList getTransactionsByWeekRange(LocalDate date, // Solution below adapted from https://stackoverflow.com/a/51356522 // Gets the range of dates for the last N number of weeks from occurring week int dayOfWeek = date.getDayOfWeek().getValue(); - LocalDate from = date.minusDays((dayOfWeek - 1) + (numberOfWeeks * 7)); + LocalDate from = date.minusDays((dayOfWeek - ONE_DAY) + + (numberOfWeeks * NUMBER_OF_DAYS_IN_A_WEEK)); LocalDate to = date.minusDays(dayOfWeek); transactionsByWeekRange = getTransactionsByDateRange(new LocalDate[]{from, to}, transactionsByWeekRange); @@ -482,8 +536,8 @@ public static ArrayList getTransactionsByMonthRange(LocalDate date, // Solution below adapted from https://stackoverflow.com/a/51356522 // Gets the range of dates for the last N number of months from occurring month - LocalDate lastMonth = date.minusMonths(1); - LocalDate from = date.minusMonths(numberOfMonths).withDayOfMonth(1); + LocalDate lastMonth = date.minusMonths(ONE_MONTH); + LocalDate from = date.minusMonths(numberOfMonths).withDayOfMonth(ONE_DAY); LocalDate to = lastMonth.withDayOfMonth(lastMonth.getMonth().maxLength()); transactionsByMonthRange = getTransactionsByDateRange(new LocalDate[]{from, to}, transactionsByMonthRange); @@ -534,11 +588,11 @@ public ArrayList getTransactionsByMonth(int year, int month) { */ public static ArrayList getTransactionsByDateRange(LocalDate[] dateRange, ArrayList transactionsByDateRange) { - for (Transaction transaction : transactions) { LocalDate transactionDate = transaction.getDate(); // Transaction is added into the filtered array list if it falls within the expected date range - if (!(transactionDate.isBefore(dateRange[START]) || transactionDate.isAfter(dateRange[END]))) { + if (!(transactionDate.isBefore(dateRange[INDEX_FOR_START_DATE]) + || transactionDate.isAfter(dateRange[INDEX_FOR_END_DATE]))) { transactionsByDateRange.add(transaction); } } diff --git a/src/main/java/seedu/duke/parser/ParameterParser.java b/src/main/java/seedu/duke/parser/ParameterParser.java index b42ddb16b..05729a25a 100644 --- a/src/main/java/seedu/duke/parser/ParameterParser.java +++ b/src/main/java/seedu/duke/parser/ParameterParser.java @@ -14,7 +14,7 @@ import seedu.duke.exception.GlobalInvalidPeriodException; import seedu.duke.exception.GlobalInvalidYearException; import seedu.duke.exception.GlobalMissingTagException; -import seedu.duke.exception.GlobalNonNumericIndexException; +import seedu.duke.exception.GlobalIndexNotNumericException; import seedu.duke.exception.GlobalNumberNotNumericException; import seedu.duke.exception.GlobalUnsupportedTagException; import seedu.duke.exception.HelpUnknownOptionException; @@ -84,6 +84,7 @@ public class ParameterParser { private static final String CATEGORICAL_SAVINGS = "categorical_savings"; private static final String MONTHLY_EXPENDITURE = "monthly_expenditure"; private static final String TIME_INSIGHTS = "time_insights"; + private static final String DAYS = "days"; private static final String WEEKS = "weeks"; private static final String MONTHS = "months"; @@ -484,14 +485,14 @@ public static int parseEntryTag(String parameter) throws MoolahException { int index; //@@chinhan99 if (containAlphabet(parameter)) { // Checks if parameter contains alphabets - throw new GlobalNonNumericIndexException(); + throw new GlobalIndexNotNumericException(); } else if (startsWithMinusSign(parameter)) { // Checks if parameter is negative value if (parameter.length() == MIN_PARAMETER_LENGTH) { //Means parameter == "-" - throw new GlobalNonNumericIndexException(); + throw new GlobalIndexNotNumericException(); } throw new GlobalInvalidIndexException(); } else if (containSymbol(parameter)) { // Checks if contains any other symbols - throw new GlobalNonNumericIndexException(); + throw new GlobalIndexNotNumericException(); } //@@author brian-vb try { @@ -634,6 +635,8 @@ public static int parseYearTag(String parameter) throws GlobalInvalidYearExcepti public static String parsePeriodTag(String parameter) throws GlobalInvalidPeriodException { String period; switch (parameter) { + case DAYS: + return DAYS; case WEEKS: return WEEKS; case MONTHS: