Skip to content
Snippets Groups Projects
Commit 7c5d860c authored by Adele Iren Westrum Kjølstad's avatar Adele Iren Westrum Kjølstad
Browse files

Added getDaysLeft method and tests

parent c8840a26
No related branches found
No related tags found
1 merge request!35Budget
Pipeline #215110 failed
package no.ntnu.idatt1002.demo.controller;
import java.time.LocalDate;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.Budget.BudgetItem;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget;
import no.ntnu.idatt1002.demo.data.Budget.GeneralBudget;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory;
import java.io.IOException;
import java.util.Optional;
import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory;
/**
* Controller for budget scene in the application. This controller manages all actions that relates to the budget tableview (add, edit and delete), the switching
* of scenes from the budget scene to another scene, and the saving of the table, whenever the user switches to another scene.
*
* @author Anders Emil Bergan
* @since 24.3.2023
*/
public class BudgetController implements FinanceController {
private GeneralBudget general;
@FXML
private Button addBtn;
@FXML
private Button editBtn;
@FXML
private Button returnBtn;
@FXML
private TableColumn<BudgetItem, Double> amountCol;
@FXML
private TableView<BudgetItem> budgetTableView = new TableView<>();
@FXML
private TableColumn<BudgetItem, ExpenseCategory> categoryCol;
@FXML
private TableColumn<BudgetItem, String> descriptionCol;
@FXML
private Text sum;
@FXML
private DatePicker date;
@FXML
private TableColumn<BudgetItem, Double> percentageColumn;
@FXML
private ObservableList<BudgetItem> budgetList;
/**
* Initializes the budget register, the observable budget list and the tableview, along with the values of the dropbox used for filtering the tableview.
* @throws IOException If there occurs any exception when loading the budget register from a file.
*/
@FXML
public void initialize() throws IOException {
//TODO if budget is not empty (HAS VALUES) -> make uneditable -> EVENT FILTER TO CONTEXT MENU
//TODO disable return to main menu when creating budget because this is the same view as when you create budeget
//TODO make budget item throw exception with negative amount
//TODO specify error messgage for when amount is exceeded / duplicate exists
//todo properly close screen so things are saved
//Initialize table columns
categoryCol.setCellValueFactory(new PropertyValueFactory<BudgetItem, ExpenseCategory>("budgetCategory"));
amountCol.setCellValueFactory(new PropertyValueFactory<BudgetItem, Double>("budgetAmount"));
descriptionCol.setCellValueFactory(new PropertyValueFactory<BudgetItem, String>("budgetDescription"));
//Initialize registers and tableview
general = loadBudgetDataFromFile("Budget");
budgetList = FXCollections.observableArrayList(general.getBudgetItems());
budgetTableView.setItems(budgetList);
formatDatePicker();
//createBudgetPieChart();
//Initialize sum field under the tableview
//sum.setText(String.valueOf(general.totalSum()));
}
private ObservableList<PieChart.Data> createBudgetPieChart() throws IllegalArgumentException { //TODO DOESNT WORK IF BUDGETITEM HAS NO BUDGET
try {
return FXCollections.observableArrayList(
new Data("Food", general.getBudgetItem(ExpenseCategory.FOOD).getBudgetAmount()),
new Data("Books", general.getBudgetItem(ExpenseCategory.BOOKS).getBudgetAmount()),
new Data("Clothes",
general.getBudgetItem(ExpenseCategory.CLOTHES).getBudgetAmount()),
new Data("Other", general.getBudgetItem(ExpenseCategory.OTHER).getBudgetAmount())
);
} catch(IllegalArgumentException iae) {
return FXCollections.observableArrayList();
}
}
/**
* Method for disabling the date picker, yet having its opacity at max.
*/
private void formatDatePicker() {
date.setValue(LocalDate.now());
date.setDisable(true);
date.setStyle("-fx-opacity: 1");
date.getEditor().setStyle("-fx-opacity: 1");
}
@Override
public void handleAddBtn(ActionEvent event) {
handleEditBtn(event);
}
/**
* Adds or edits a budget item, depending on what mode the DialogMode enum is at. The method brings up a dialog box popup in which the user can fill and choose
* values that the budget item will have. Open exiting the popup, the changes the saved to the tableview.
* @param event A button click on either the add or delete button.
*/
@Override
public void handleEditBtn(ActionEvent event) {
BudgetItem item = null;
String dialogTitle = "";
DialogMode dialogMode;
FXMLLoader loader = new FXMLLoader(SceneController.class.getResource("/view/AddBudgetNew.fxml"));
Dialog<BudgetItem> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
//Try to load the FXML file onto another dialogPane
try{
dialog.getDialogPane().setContent(loader.load());
} catch(IOException e) {
e.printStackTrace();
}
//Loads the controller for the dialog box that appears whenever one adds or edits a budget item
AddBudgetController budgetController = loader.getController();
//Sets the title of the dialog box
if(event.getSource().equals(addBtn)){
dialogMode = DialogMode.ADD;
dialogTitle = "New Budget";
}
else if (event.getSource().equals(editBtn) && budgetTableView.getSelectionModel().getSelectedItem() != null) {
dialogMode = DialogMode.EDIT;
dialogTitle = "Edit expense";
//Gets the selected item from the table
item = budgetTableView.getSelectionModel().getSelectedItem();
//Binds the selected item to another item which is defined in the budgetcontroller
budgetController.setBudget(item);
} else {
return;
}
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
//Adds the new item to the register
item = budgetController.getNewBudgetItem();
if(item != null && dialogMode == DialogMode.ADD){
try {
general.addToBudgetBudgetItem(item);
} catch(IllegalArgumentException e) {
showIllegalBudgetItemDialog();
}
}
//Updates the tableview using the register
refreshTableView();
}
/**
* Deletes an entry from the tableview, if an entry has been selected. The method brings up a popup window, asking for confirmation for deleting the entry.
* @param event A button click on the delete button
*/
@FXML
public void handleDeleteBtn(ActionEvent event) {
//Gets the selected item from the tableview
BudgetItem item = budgetTableView.getSelectionModel().getSelectedItem();
//Exits the method if nothing is selected
if (item == null) {
return;
}
//Brings up a confirmation popup
Optional<ButtonType> isConfirmed = showConfirmationDialog();
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
general.deleteItemFromBudget(item.getBudgetCategory());
refreshTableView();
}
}
/**
* Method for synching the register with the tableview. The observable list to which the tableview is set, is being refilled with all the entries
* in the register, keeping it updated with new changes.
*/
public void refreshTableView(){
this.budgetList.setAll(general.getBudgetItems());
//Refreshing the sum of the amounts of the budget
//this.sum.setText(String.valueOf(general.totalSum()));
}
/**
* Returns an optional, which is a popup alert box, asking for confirmation for deleting an entry.
* @return An alert box, asking for confirmation for deleting the selected entry of the tableview.
*/
@Override
public Optional<ButtonType> showConfirmationDialog() {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirm Delete");
alert.setHeaderText("Delete Confirmation");
alert.setContentText("Are you sure you would like to delete the selected entry?");
return alert.showAndWait();
}
/**
* Saves the changes made to the tableview by writing the information to a file.
*
* @throws IOException If an error occurs while writing to the file.
*/
@Override
public void saveDataToFile() throws IOException {
FileHandlingBudget fileHandlingBudget = new FileHandlingBudget();
fileHandlingBudget.writeGeneralBudgetToFile("Budget", general);
}
/**
* Returns an optional, which is a popup alert box, informing that either the budget amount has
* been exceeded or that the same category has been entered twice in the budget tableview.
*/
private void showIllegalBudgetItemDialog() {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Budget amount exceeded/Category already exists");
alert.setHeaderText("Your budget exceeds the max limit OR a budget item of the same category already exists in the table");
alert.setContentText("The total budget sum must be below " + general.getMaxAmount() + " OR Each category can only have one entry in the budget table");
alert.showAndWait();
}
/**
* Method that either reads data from a file with which it fills a budget register, if this is an old budget, or instantiates a budget register if this is a new budget.
* @param fileName The name of the file that is being read from.
* @return An object of type GeneralBudget.
* @throws IOException If an error occurs while reading from the file.
*/
public GeneralBudget loadBudgetDataFromFile(String fileName) throws IOException {
FileHandlingBudget fileHandlingBudget = new FileHandlingBudget();
//Instantiate new budget
if (fileHandlingBudget.isEmpty(fileName)) {
general = new GeneralBudget(31, 1000);
//throws new IOException("Not valid budget")
} else { //Load previous budget
try {
general = fileHandlingBudget.readGeneralBudgetFromFile(fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
return general;
}
/**
* Switches scenes back to main menu, by loading a new FXML file and setting the scene to this location.
* @param event A button click on the return to main menu button
* @throws IOException If an error occurs with loading any of the FXML files.
*/
@FXML
public void returnToMainMenu(ActionEvent event) throws IOException {
//Always saving the data when switching scenes
saveDataToFile();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/MainMenuNew.fxml"));
Parent root = loader.load();
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
package no.ntnu.idatt1002.demo.controller;
public class budgetController {
}
......@@ -5,6 +5,7 @@ import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory;
import java.sql.Date;
import java.time.Duration;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
......@@ -110,22 +111,16 @@ public class GeneralBudget {
}
/**
* This method returns the amount of days left in the budget period as a string.
* This method returns the amount of days left in the budget period as a long.
*
* @return the amount of days left in the budget period
*
*/
public long getDaysLeftOfBudgetPeriod() {
LocalDate today = LocalDate.now();
LocalDate end = today.plus(Duration.ofDays(getBudgetPeriod()));
Month thisMonth = LocalDate.now().getMonth();
int dayOfTheMonth = LocalDate.now().getDayOfMonth();
Date todaysDate = (Date) Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
Date endDate = (Date) Date.from(end.atStartOfDay(ZoneId.systemDefault()).toInstant());
Calendar cStart = Calendar.getInstance(); cStart.setTime(todaysDate);
Calendar cEnd = Calendar.getInstance(); cEnd.setTime(endDate);
return ChronoUnit.DAYS.between((Temporal) cStart, (Temporal) cEnd);
return thisMonth.maxLength() - dayOfTheMonth;
}
/**
......
......@@ -104,4 +104,13 @@ class GeneralBudgetTest {
assertTrue(list.isEmpty());
}
@Test
@DisplayName("Gets the number of days left in the month. 17 has to be changed to the actual number of days left in the month.")
void get_days_left_of_the_month(){
List<BudgetItem> list = new ArrayList<>();
GeneralBudget budget1 = new GeneralBudget(12, list, 1200);
assertEquals(17, budget1.getDaysLeftOfBudgetPeriod());
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment