Added historical balance checker and cleaned up actions layout on account page.

This commit is contained in:
Andrew Lalis 2024-02-07 09:05:50 -05:00
parent 104de66a66
commit 6bafd06fc0
3 changed files with 90 additions and 41 deletions

View File

@ -2,17 +2,25 @@ package com.andrewlalis.perfin.control;
import com.andrewlalis.javafx_scene_router.RouteSelectionListener;
import com.andrewlalis.perfin.data.AccountRepository;
import com.andrewlalis.perfin.data.util.CurrencyUtil;
import com.andrewlalis.perfin.data.util.DateUtil;
import com.andrewlalis.perfin.model.Account;
import com.andrewlalis.perfin.model.MoneyValue;
import com.andrewlalis.perfin.model.Profile;
import com.andrewlalis.perfin.view.component.AccountHistoryView;
import com.andrewlalis.perfin.view.component.validation.ValidationApplier;
import com.andrewlalis.perfin.view.component.validation.validators.PredicateValidator;
import javafx.application.Platform;
import javafx.beans.binding.BooleanExpression;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import java.time.*;
import static com.andrewlalis.perfin.PerfinApp.router;
@ -30,10 +38,13 @@ public class AccountViewController implements RouteSelectionListener {
@FXML public AccountHistoryView accountHistory;
@FXML public VBox actionsVBox;
@FXML public HBox actionsBox;
@FXML public DatePicker balanceCheckerDatePicker;
@FXML public Button balanceCheckerButton;
@FXML public void initialize() {
actionsVBox.getChildren().forEach(node -> {
actionsBox.getChildren().forEach(node -> {
Button button = (Button) node;
BooleanExpression buttonActive = accountArchivedProperty;
if (button.getText().equalsIgnoreCase("Unarchive")) {
@ -43,6 +54,28 @@ public class AccountViewController implements RouteSelectionListener {
button.managedProperty().bind(button.visibleProperty());
button.visibleProperty().bind(button.disableProperty().not());
});
var datePickerValid = new ValidationApplier<>(new PredicateValidator<LocalDate>()
.addPredicate(date -> date.isBefore(LocalDate.now()), "Date must be in the past.")
).attach(balanceCheckerDatePicker, balanceCheckerDatePicker.valueProperty());
balanceCheckerButton.disableProperty().bind(datePickerValid.not());
balanceCheckerButton.setOnAction(event -> {
LocalDate date = balanceCheckerDatePicker.getValue();
final Instant timestamp = date.atStartOfDay(ZoneId.systemDefault())
.withZoneSameInstant(ZoneOffset.UTC)
.toInstant();
Profile.getCurrent().dataSource().mapRepoAsync(
AccountRepository.class,
repo -> repo.deriveBalance(account.id, timestamp)
).thenAccept(balance -> Platform.runLater(() -> {
String msg = String.format(
"Your balance as of %s is %s, according to Perfin's data.",
date,
CurrencyUtil.formatMoney(new MoneyValue(balance, account.getCurrency()))
);
Popups.message(balanceCheckerButton, msg);
}));
});
}
@Override

View File

@ -81,6 +81,7 @@ public class StyledText extends VBox {
idx = 0;
currentRun.setLength(0);
currentParagraph = new TextFlow();
currentParagraph.setStyle("-fx-text-fill: inherit;");
while (idx < text.length()) {
if (text.startsWith("**", idx)) {
@ -118,6 +119,7 @@ public class StyledText extends VBox {
int endIdx = text.indexOf(marker, idx + marker.length());
Text textItem = new Text(text.substring(idx + marker.length(), endIdx));
textItem.getStyleClass().add(styleClass);
textItem.setStyle("-fx-text-fill: inherit;");
currentParagraph.getChildren().add(textItem);
idx = endIdx + marker.length();
}
@ -183,6 +185,7 @@ public class StyledText extends VBox {
if (!currentParagraph.getChildren().isEmpty()) {
flows.add(currentParagraph);
currentParagraph = new TextFlow();
currentParagraph.setStyle("-fx-text-fill: inherit;");
}
}
}

View File

@ -5,6 +5,8 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Text?>
<?import com.andrewlalis.perfin.view.component.StyledText?>
<?import javafx.scene.text.TextFlow?>
<BorderPane
xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
@ -16,10 +18,7 @@
<center>
<VBox>
<!-- Main account properties and actions -->
<BorderPane>
<center>
<VBox styleClass="std-padding,std-spacing">
<FlowPane>
<FlowPane styleClass="std-padding,std-spacing">
<!-- Main account properties. -->
<PropertiesPane vgap="5" hgap="5">
<Label text="Name" styleClass="bold-text"/>
@ -44,21 +43,35 @@
<Label fx:id="accountBalanceLabel" styleClass="mono-font"/>
</PropertiesPane>
</FlowPane>
</VBox>
</center>
<right>
<!-- Action buttons -->
<HBox fx:id="actionsBox" styleClass="std-padding,std-spacing,small-font">
<Button text="Edit" onAction="#goToEditPage"/>
<Button text="Record Balance" onAction="#goToCreateBalanceRecord"/>
<Button text="Archive" onAction="#archiveAccount"/>
<Button text="Delete" onAction="#deleteAccount"/>
<Button text="Unarchive" onAction="#unarchiveAccount"/>
</HBox>
<!-- Historical Balance Checker -->
<VBox styleClass="std-padding,std-spacing">
<Label text="Actions" styleClass="bold-text"/>
<VBox fx:id="actionsVBox" styleClass="std-spacing">
<Button text="Edit" onAction="#goToEditPage" maxWidth="Infinity"/>
<Button text="Record Balance" onAction="#goToCreateBalanceRecord" maxWidth="Infinity"/>
<Button text="Archive" onAction="#archiveAccount" maxWidth="Infinity"/>
<Button text="Delete" onAction="#deleteAccount" maxWidth="Infinity"/>
<Button text="Unarchive" onAction="#unarchiveAccount" maxWidth="Infinity"/>
<HBox styleClass="std-spacing">
<AnchorPane>
<Label text="Check Historical Balance" styleClass="bold-text" AnchorPane.topAnchor="0" AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"/>
</AnchorPane>
<DatePicker fx:id="balanceCheckerDatePicker"/>
<Button text="Check" fx:id="balanceCheckerButton"/>
</HBox>
<TextFlow maxWidth="500">
<Text styleClass="small-font,secondary-color-fill">
Use this tool to check the balance of this account on any
given day in the past. Perfin will compute the balance
according to any balance records and transactions it finds
around that time.
</Text>
</TextFlow>
</VBox>
</VBox>
</right>
</BorderPane>
<!-- Account history -->
<VBox VBox.vgrow="ALWAYS">