Added the ability to delete balance records, and added additional history handling for deleted information.
This commit is contained in:
parent
ed6e2fba4a
commit
087242396d
|
@ -43,6 +43,10 @@ public class AccountViewController implements RouteSelectionListener {
|
|||
accountCreatedAtField.setText(DateUtil.formatUTCAsLocalWithZone(account.getCreatedAt()));
|
||||
Profile.getCurrent().getDataSource().getAccountBalanceText(account, accountBalanceField::setText);
|
||||
|
||||
reloadHistory();
|
||||
}
|
||||
|
||||
public void reloadHistory() {
|
||||
loadHistoryFrom = DateUtil.nowAsUTC();
|
||||
historyItemsVBox.getChildren().clear();
|
||||
loadMoreHistoryButton.setDisable(false);
|
||||
|
@ -106,7 +110,7 @@ public class AccountViewController implements RouteSelectionListener {
|
|||
loadHistoryFrom = historyItems.getLast().getTimestamp();
|
||||
}
|
||||
List<? extends Node> nodes = historyItems.stream()
|
||||
.map(item -> new AccountHistoryItemTile(item, historyRepo))
|
||||
.map(item -> AccountHistoryItemTile.forItem(item, historyRepo, this))
|
||||
.toList();
|
||||
Platform.runLater(() -> historyItemsVBox.getChildren().addAll(nodes));
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -7,7 +7,10 @@ import com.andrewlalis.perfin.model.Profile;
|
|||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
@ -88,12 +91,7 @@ public class EditAccountController implements RouteSelectionListener {
|
|||
BigDecimal initialBalance = new BigDecimal(initialBalanceField.getText().strip());
|
||||
List<Path> attachments = Collections.emptyList();
|
||||
|
||||
Alert confirm = new Alert(
|
||||
Alert.AlertType.CONFIRMATION,
|
||||
"Are you sure you want to create this account?"
|
||||
);
|
||||
Optional<ButtonType> result = confirm.showAndWait();
|
||||
boolean success = result.isPresent() && result.get().equals(ButtonType.OK);
|
||||
boolean success = Popups.confirm("Are you sure you want to create this account?");
|
||||
if (success) {
|
||||
long id = accountRepo.insert(type, number, name, currency);
|
||||
balanceRepo.insert(LocalDateTime.now(ZoneOffset.UTC), id, initialBalance, currency, attachments);
|
||||
|
|
|
@ -18,6 +18,7 @@ public interface AccountRepository extends AutoCloseable {
|
|||
Page<Account> findAll(PageRequest pagination);
|
||||
List<Account> findAllByCurrency(Currency currency);
|
||||
Optional<Account> findById(long id);
|
||||
void updateName(long id, String name);
|
||||
void update(Account account);
|
||||
void delete(Account account);
|
||||
void archive(Account account);
|
||||
|
|
|
@ -11,4 +11,5 @@ import java.util.List;
|
|||
public interface BalanceRecordRepository extends AutoCloseable {
|
||||
long insert(LocalDateTime utcTimestamp, long accountId, BigDecimal balance, Currency currency, List<Path> attachments);
|
||||
BalanceRecord findLatestByAccountId(long accountId);
|
||||
void deleteById(long id);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,11 @@ public record JdbcAccountRepository(Connection conn) implements AccountRepositor
|
|||
return DbUtil.findById(conn, "SELECT * FROM account WHERE id = ?", id, JdbcAccountRepository::parseAccount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateName(long id, String name) {
|
||||
DbUtil.updateOne(conn, "UPDATE account SET name = ? WHERE id = ?", List.of(name, id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal deriveBalance(long id, Instant timestamp) {
|
||||
// Find the most recent balance record before timestamp.
|
||||
|
|
|
@ -51,6 +51,11 @@ public record JdbcBalanceRecordRepository(Connection conn, Path contentDir) impl
|
|||
).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteById(long id) {
|
||||
DbUtil.updateOne(conn, "DELETE FROM balance_record WHERE id = ?", List.of(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
conn.close();
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package com.andrewlalis.perfin.view.component;
|
||||
|
||||
import com.andrewlalis.perfin.control.TransactionsViewController;
|
||||
import com.andrewlalis.perfin.data.AccountHistoryItemRepository;
|
||||
import com.andrewlalis.perfin.data.util.CurrencyUtil;
|
||||
import com.andrewlalis.perfin.model.AccountEntry;
|
||||
import com.andrewlalis.perfin.model.history.AccountHistoryItem;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
import static com.andrewlalis.perfin.PerfinApp.router;
|
||||
|
||||
public class AccountHistoryAccountEntryTile extends AccountHistoryItemTile {
|
||||
public AccountHistoryAccountEntryTile(AccountHistoryItem item, AccountHistoryItemRepository repo) {
|
||||
super(item);
|
||||
AccountEntry entry = repo.getAccountEntryItem(item.getId());
|
||||
if (entry == null) {
|
||||
setCenter(new TextFlow(new Text("Deleted account entry because of deleted transaction.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Text amountText = new Text(CurrencyUtil.formatMoneyWithCurrencyPrefix(entry.getMoneyValue()));
|
||||
Hyperlink transactionLink = new Hyperlink("Transaction #" + entry.getTransactionId());
|
||||
transactionLink.setOnAction(event -> router.navigate(
|
||||
"transactions",
|
||||
new TransactionsViewController.RouteContext(entry.getTransactionId())
|
||||
));
|
||||
var text = new TextFlow(
|
||||
transactionLink,
|
||||
new Text("posted as a " + entry.getType().name().toLowerCase() + " to this account, with a value of "),
|
||||
amountText
|
||||
);
|
||||
setCenter(text);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.andrewlalis.perfin.view.component;
|
||||
|
||||
import com.andrewlalis.perfin.control.AccountViewController;
|
||||
import com.andrewlalis.perfin.control.Popups;
|
||||
import com.andrewlalis.perfin.data.AccountHistoryItemRepository;
|
||||
import com.andrewlalis.perfin.data.util.CurrencyUtil;
|
||||
import com.andrewlalis.perfin.model.BalanceRecord;
|
||||
import com.andrewlalis.perfin.model.Profile;
|
||||
import com.andrewlalis.perfin.model.history.AccountHistoryItem;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
public class AccountHistoryBalanceRecordTile extends AccountHistoryItemTile {
|
||||
public AccountHistoryBalanceRecordTile(AccountHistoryItem item, AccountHistoryItemRepository repo, AccountViewController controller) {
|
||||
super(item);
|
||||
BalanceRecord balanceRecord = repo.getBalanceRecordItem(item.getId());
|
||||
if (balanceRecord == null) {
|
||||
setCenter(new TextFlow(new Text("Deleted balance record was added.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Text amountText = new Text(CurrencyUtil.formatMoneyWithCurrencyPrefix(balanceRecord.getMoneyAmount()));
|
||||
var text = new TextFlow(new Text("Balance record #" + balanceRecord.getId() + " added with value of "), amountText);
|
||||
setCenter(text);
|
||||
|
||||
Hyperlink deleteLink = new Hyperlink("Delete this balance record");
|
||||
deleteLink.setOnAction(event -> {
|
||||
boolean confirm = Popups.confirm("Are you sure you want to delete this balance record? It will be removed permanently, and cannot be undone.");
|
||||
if (confirm) {
|
||||
Profile.getCurrent().getDataSource().useBalanceRecordRepository(balanceRecordRepo -> {
|
||||
balanceRecordRepo.deleteById(balanceRecord.getId());
|
||||
Platform.runLater(controller::reloadHistory);
|
||||
});
|
||||
}
|
||||
});
|
||||
setBottom(deleteLink);
|
||||
}
|
||||
}
|
|
@ -1,26 +1,17 @@
|
|||
package com.andrewlalis.perfin.view.component;
|
||||
|
||||
import com.andrewlalis.perfin.control.TransactionsViewController;
|
||||
import com.andrewlalis.perfin.control.AccountViewController;
|
||||
import com.andrewlalis.perfin.data.AccountHistoryItemRepository;
|
||||
import com.andrewlalis.perfin.data.util.CurrencyUtil;
|
||||
import com.andrewlalis.perfin.data.util.DateUtil;
|
||||
import com.andrewlalis.perfin.model.AccountEntry;
|
||||
import com.andrewlalis.perfin.model.BalanceRecord;
|
||||
import com.andrewlalis.perfin.model.history.AccountHistoryItem;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
import static com.andrewlalis.perfin.PerfinApp.router;
|
||||
|
||||
/**
|
||||
* A tile that shows a brief bit of information about an account history item.
|
||||
*/
|
||||
public class AccountHistoryItemTile extends BorderPane {
|
||||
public AccountHistoryItemTile(AccountHistoryItem item, AccountHistoryItemRepository repo) {
|
||||
public abstract class AccountHistoryItemTile extends BorderPane {
|
||||
public AccountHistoryItemTile(AccountHistoryItem item) {
|
||||
setStyle("""
|
||||
-fx-border-color: lightgray;
|
||||
-fx-border-radius: 5px;
|
||||
|
@ -30,33 +21,17 @@ public class AccountHistoryItemTile extends BorderPane {
|
|||
Label timestampLabel = new Label(DateUtil.formatUTCAsLocalWithZone(item.getTimestamp()));
|
||||
timestampLabel.setStyle("-fx-font-size: small;");
|
||||
setTop(timestampLabel);
|
||||
setCenter(switch (item.getType()) {
|
||||
case TEXT -> buildTextItem(repo.getTextItem(item.getId()));
|
||||
case ACCOUNT_ENTRY -> buildAccountEntryItem(repo.getAccountEntryItem(item.getId()));
|
||||
case BALANCE_RECORD -> buildBalanceRecordItem(repo.getBalanceRecordItem(item.getId()));
|
||||
});
|
||||
}
|
||||
|
||||
private Node buildTextItem(String text) {
|
||||
return new TextFlow(new Text(text));
|
||||
}
|
||||
|
||||
private Node buildAccountEntryItem(AccountEntry entry) {
|
||||
Text amountText = new Text(CurrencyUtil.formatMoneyWithCurrencyPrefix(entry.getMoneyValue()));
|
||||
Hyperlink transactionLink = new Hyperlink("Transaction #" + entry.getTransactionId());
|
||||
transactionLink.setOnAction(event -> router.navigate(
|
||||
"transactions",
|
||||
new TransactionsViewController.RouteContext(entry.getTransactionId())
|
||||
));
|
||||
return new TextFlow(
|
||||
transactionLink,
|
||||
new Text("posted as a " + entry.getType().name().toLowerCase() + " to this account, with a value of "),
|
||||
amountText
|
||||
);
|
||||
}
|
||||
|
||||
private Node buildBalanceRecordItem(BalanceRecord balanceRecord) {
|
||||
Text amountText = new Text(CurrencyUtil.formatMoneyWithCurrencyPrefix(balanceRecord.getMoneyAmount()));
|
||||
return new TextFlow(new Text("Balance record #" + balanceRecord.getId() + " added with value of "), amountText);
|
||||
public static AccountHistoryItemTile forItem(
|
||||
AccountHistoryItem item,
|
||||
AccountHistoryItemRepository repo,
|
||||
AccountViewController controller
|
||||
) {
|
||||
return switch (item.getType()) {
|
||||
case TEXT -> new AccountHistoryTextTile(item, repo);
|
||||
case ACCOUNT_ENTRY -> new AccountHistoryAccountEntryTile(item, repo);
|
||||
case BALANCE_RECORD -> new AccountHistoryBalanceRecordTile(item, repo, controller);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.andrewlalis.perfin.view.component;
|
||||
|
||||
import com.andrewlalis.perfin.data.AccountHistoryItemRepository;
|
||||
import com.andrewlalis.perfin.model.history.AccountHistoryItem;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
public class AccountHistoryTextTile extends AccountHistoryItemTile {
|
||||
public AccountHistoryTextTile(AccountHistoryItem item, AccountHistoryItemRepository repo) {
|
||||
super(item);
|
||||
String text = repo.getTextItem(item.getId());
|
||||
setCenter(new TextFlow(new Text(text)));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue