Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add budget V1 #75

Merged
merged 21 commits into from
Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
48b56ad
safe delete Address class
choonx99 Sep 27, 2019
840b067
Merge pull request #1 from choonx99/tutorial-removing-field
choonx99 Sep 27, 2019
97330d3
Merge branch 'master' of https://github.com/choonx99/main
choonx99 Oct 2, 2019
da8dc7c
Remove trailing white space from contactus doc
choonx99 Oct 2, 2019
747b2cc
Merge branch 'master' of https://github.com/choonx99/main into update…
choonx99 Oct 2, 2019
8e876a3
Merge branch 'update-pages' of https://github.com/choonx99/main into …
choonx99 Oct 2, 2019
7d7adfa
Merge pull request #3 from AY1920S1-CS2103-T14-4/master
choonx99 Oct 2, 2019
4bd44b9
Merge branch 'master' of https://github.com/AY1920S1-CS2103-T14-4/main
choonx99 Oct 9, 2019
26e26b6
Merge pull request #4 from choonx99/update-pages
choonx99 Oct 9, 2019
ce3e122
Merge branch 'master' of https://github.com/choonx99/main
choonx99 Oct 9, 2019
089ab6a
Merge branch 'master' of https://github.com/AY1920S1-CS2103-T14-4/main
choonx99 Oct 9, 2019
76ee55e
revert removeAddr merge
choonx99 Oct 9, 2019
439fbfe
Merge branch 'master' of https://github.com/AY1920S1-CS2103-T14-4/main
choonx99 Oct 10, 2019
924c02b
Merge branch 'master' of https://github.com/AY1920S1-CS2103-T14-4/main
choonx99 Oct 16, 2019
77fc400
Merge branch 'master' of https://github.com/AY1920S1-CS2103-T14-4/main
choonx99 Oct 16, 2019
c43ce95
added add budget function, checks to prevent budget period clashes, e…
choonx99 Oct 21, 2019
7db015d
Fixed test cases for add budget
choonx99 Oct 22, 2019
d879fea
fixed expenselist storage inside budget and checkstyle errors
choonx99 Oct 22, 2019
0172a6b
fix checkstyle error
choonx99 Oct 22, 2019
1085fc8
fixed checkstyle error
choonx99 Oct 22, 2019
f62c9bf
Merge pull request #71 from choonx99/Add_Budget
Cary-Xx Oct 23, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/main/java/seedu/address/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@
import seedu.address.model.ReadOnlyExpenseList;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.UserPrefs;
import seedu.address.model.budget.BudgetList;
import seedu.address.model.budget.ReadOnlyBudgetList;
import seedu.address.model.util.SampleDataUtil;

import seedu.address.storage.BudgetListStorage;
import seedu.address.storage.ExpenseListStorage;
import seedu.address.storage.JsonBudgetListStorage;
import seedu.address.storage.JsonExpenseListStorage;
import seedu.address.storage.JsonUserPrefsStorage;
import seedu.address.storage.Storage;
Expand Down Expand Up @@ -57,7 +62,8 @@ public void init() throws Exception {
UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath());
UserPrefs userPrefs = initPrefs(userPrefsStorage);
ExpenseListStorage expenseListStorage = new JsonExpenseListStorage(userPrefs.getExpenseListFilePath());
storage = new StorageManager(expenseListStorage, userPrefsStorage);
BudgetListStorage budgetListStorage = new JsonBudgetListStorage(userPrefs.getBudgetListFilePath());
storage = new StorageManager(expenseListStorage, budgetListStorage, userPrefsStorage);

initLogging(config);

Expand All @@ -75,7 +81,9 @@ public void init() throws Exception {
*/
private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
Optional<ReadOnlyExpenseList> expenseListOptional;
Optional<ReadOnlyBudgetList> budgetListOptional;
ReadOnlyExpenseList initialData;
ReadOnlyBudgetList initialBudgets;
try {
expenseListOptional = storage.readExpenseList();
if (!expenseListOptional.isPresent()) {
Expand All @@ -90,7 +98,21 @@ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
initialData = new ExpenseList();
}

return new ModelManager(initialData, userPrefs);
try {
budgetListOptional = storage.readBudgetList();
if (!budgetListOptional.isPresent()) {
logger.info("Data file not found. Will be starting with a sample BudgetList");
}
initialBudgets = budgetListOptional.orElseGet(SampleDataUtil::getSampleBudgetList);
} catch (DataConversionException e) {
logger.warning("Data file not in the correct format. Will be starting with an empty BudgetList");
initialBudgets = new BudgetList();
} catch (IOException e) {
logger.warning("Problem while reading from the file. Will be starting with an empty BudgetList");
initialBudgets = new BudgetList();
}

return new ModelManager(initialData, initialBudgets, userPrefs);
}

private void initLogging(Config config) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
}

try {
storage.saveBudgetList(model.getBudgetList());
} catch (IOException ioe) {
throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe);
}

return commandResult;
}

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

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_AMOUNT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_END_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.budget.Budget;

/**
* Adds a budget into the budget list.
*/
public class AddBudgetCommand extends Command {

public static final String COMMAND_WORD = "budget";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a budget to the budget list.\n"
+ "Parameters: "
+ PREFIX_NAME + "NAME "
+ PREFIX_AMOUNT + "AMOUNT "
+ PREFIX_DATE + "START-DATE "
+ PREFIX_END_DATE + "END-DATE...\n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_NAME + "Japan Travel "
+ PREFIX_AMOUNT + "$2000.00 "
+ PREFIX_DATE + "12/12/2019 "
+ PREFIX_END_DATE + "18/12/2019\n";


public static final String MESSAGE_SUCCESS = "New budget added: %1$s";
public static final String MESSAGE_DUPLICATE_BUDGET = "This budget already exists in the budget list";
public static final String MESSAGE_BUDGET_CLASH = "This budget period clashes with another budget";
public static final String MESSAGE_START_BEFORE_END = "The budget end date has to be after its start date";

private final Budget toAdd;

/**
* Creates an AddBudgetCommand to add the specified {@code Budget}
*/
public AddBudgetCommand(Budget budget) {
requireNonNull(budget);
toAdd = budget;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);

if (toAdd.getEndDate().localDate.isBefore(toAdd.getStartDate().localDate)) {
throw new CommandException(MESSAGE_START_BEFORE_END);
}

if (model.hasBudgetPeriodClash(toAdd)) {
throw new CommandException(MESSAGE_BUDGET_CLASH);
}

if (model.hasBudget(toAdd)) {
throw new CommandException(MESSAGE_DUPLICATE_BUDGET);
}

model.addBudget(toAdd);
return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
}
}
1 change: 1 addition & 0 deletions src/main/java/seedu/address/logic/commands/AddCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import seedu.address.model.Model;
import seedu.address.model.expense.Expense;


/**
* Adds an expense to the expense list.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package seedu.address.logic.parser;

import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_AMOUNT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_END_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;

import java.util.stream.Stream;

import seedu.address.logic.commands.AddBudgetCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.ExpenseList;
import seedu.address.model.budget.Budget;
import seedu.address.model.expense.Amount;
import seedu.address.model.expense.Date;
import seedu.address.model.expense.Name;

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

/**
* Parses the given {@code String} of arguments in the context of the AddBudgetCommand
* and returns an AddBudgetCommand object for execution.
*
* @throws ParseException if the user input does not conform the expected format
*/
public AddBudgetCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_AMOUNT, PREFIX_DATE, PREFIX_END_DATE);

if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_AMOUNT, PREFIX_DATE, PREFIX_END_DATE)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddBudgetCommand.MESSAGE_USAGE));
}

Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
Amount amount = ParserUtil.parseAmount(argMultimap.getValue(PREFIX_AMOUNT).get());
Date startDate = ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get());
Date endDate = ParserUtil.parseDate(argMultimap.getValue(PREFIX_END_DATE).get());

Budget budget = new Budget(name, amount, amount, startDate, endDate, new ExpenseList());

return new AddBudgetCommand(budget);
}

private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}
}
1 change: 1 addition & 0 deletions src/main/java/seedu/address/logic/parser/CliSyntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class CliSyntax {
public static final Prefix PREFIX_AMOUNT = new Prefix("a/");
public static final Prefix PREFIX_CURRENCY = new Prefix("c/");
public static final Prefix PREFIX_DATE = new Prefix("d/");
public static final Prefix PREFIX_END_DATE = new Prefix("ed/");
public static final Prefix PREFIX_TAG = new Prefix("t/");

}
4 changes: 4 additions & 0 deletions src/main/java/seedu/address/logic/parser/MymParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import seedu.address.logic.commands.AddBudgetCommand;
import seedu.address.logic.commands.AddCommand;
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.Command;
Expand Down Expand Up @@ -68,6 +69,9 @@ public Command parseCommand(String userInput) throws ParseException {
case HelpCommand.COMMAND_WORD:
return new HelpCommand();

case AddBudgetCommand.COMMAND_WORD:
return new AddBudgetCommandParser().parse(arguments);

default:
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
}
Expand Down
62 changes: 62 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package seedu.address.model;

import java.nio.file.Path;
import java.util.Optional;
import java.util.function.Predicate;

import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
import seedu.address.model.budget.Budget;
import seedu.address.model.budget.ReadOnlyBudgetList;
import seedu.address.model.expense.Expense;

/**
Expand All @@ -13,6 +16,7 @@
public interface Model {
/** {@code Predicate} that always evaluate to true */
Predicate<Expense> PREDICATE_SHOW_ALL_EXPENSES = unused -> true;
Predicate<Budget> PREDICATE_SHOW_ALL_BUDGETS = unused -> true;

/**
* Replaces user prefs data with the data in {@code userPrefs}.
Expand Down Expand Up @@ -85,4 +89,62 @@ public interface Model {
* @throws NullPointerException if {@code predicate} is null.
*/
void updateFilteredExpenseList(Predicate<Expense> predicate);

/**
* Returns the user prefs' budget list file path.
*/
Path getBudgetListFilePath();

/**
* Sets the user prefs' budget list file path.
*/
void setBudgetListFilePath(Path expenseListFilePath);

/**
* Replaces budget list data with the data in {@code budgetList}.
*/
void setBudgetList(ReadOnlyBudgetList budgetList);

/** Returns the BudgetList */
ReadOnlyBudgetList getBudgetList();

/**
* Returns true if a budget with the same identity as {@code budget} exists in the budget list.
*/
boolean hasBudget(Budget budget);

/**
* Deletes the given budget.
* The budget must exist in the budget list.
*/
void deleteBudget(Budget target);

/**
* Adds the given budget.
* {@code budget} must not already exist in the budget list.
*/
void addBudget(Budget budget);

/**
* Replaces the given budget {@code target} with {@code editedBudget}.
* {@code target} must exist in the budget list.
* The budget identity of {@code editedBudget} must not be the same as
* another existing budget in the budget list.
*/
void setBudget(Budget target, Budget editedBudget);

/** Returns an unmodifiable view of the filtered budget list */
ObservableList<Budget> getFilteredBudgetList();

/**
* Updates the filter of the filtered budget list to filter by the given {@code predicate}.
* @throws NullPointerException if {@code predicate} is null.
*/
void updateFilteredBudgetList(Predicate<Budget> predicate);

boolean hasBudgetPeriodClash(Budget newBudget);

Optional<Budget> getBudgetExpenseFallsInto(Expense expense);

boolean expenseFallsIntoABudget(Expense expense);
}
Loading