Refactored the account-view.fxml and associated stuff to include the account's description.
This commit is contained in:
parent
b52148fd3b
commit
7f65466d6d
|
@ -7,34 +7,39 @@ import com.andrewlalis.perfin.data.util.DateUtil;
|
||||||
import com.andrewlalis.perfin.model.Account;
|
import com.andrewlalis.perfin.model.Account;
|
||||||
import com.andrewlalis.perfin.model.MoneyValue;
|
import com.andrewlalis.perfin.model.MoneyValue;
|
||||||
import com.andrewlalis.perfin.model.Profile;
|
import com.andrewlalis.perfin.model.Profile;
|
||||||
|
import com.andrewlalis.perfin.view.BindingUtil;
|
||||||
import com.andrewlalis.perfin.view.component.AccountHistoryView;
|
import com.andrewlalis.perfin.view.component.AccountHistoryView;
|
||||||
|
import com.andrewlalis.perfin.view.component.PropertiesPane;
|
||||||
import com.andrewlalis.perfin.view.component.validation.ValidationApplier;
|
import com.andrewlalis.perfin.view.component.validation.ValidationApplier;
|
||||||
import com.andrewlalis.perfin.view.component.validation.validators.PredicateValidator;
|
import com.andrewlalis.perfin.view.component.validation.validators.PredicateValidator;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.BooleanExpression;
|
import javafx.beans.binding.BooleanExpression;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.*;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.DatePicker;
|
import javafx.scene.control.DatePicker;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
|
|
||||||
import static com.andrewlalis.perfin.PerfinApp.router;
|
import static com.andrewlalis.perfin.PerfinApp.router;
|
||||||
|
|
||||||
public class AccountViewController implements RouteSelectionListener {
|
public class AccountViewController implements RouteSelectionListener {
|
||||||
private Account account;
|
private final ObjectProperty<Account> accountProperty = new SimpleObjectProperty<>(null);
|
||||||
|
private final ObservableValue<Boolean> accountArchived = accountProperty.map(a -> a != null && a.isArchived());
|
||||||
|
private final StringProperty balanceTextProperty = new SimpleStringProperty(null);
|
||||||
|
|
||||||
@FXML public Label titleLabel;
|
@FXML public Label titleLabel;
|
||||||
|
|
||||||
@FXML public Label accountNameLabel;
|
@FXML public Label accountNameLabel;
|
||||||
@FXML public Label accountNumberLabel;
|
@FXML public Label accountNumberLabel;
|
||||||
@FXML public Label accountCurrencyLabel;
|
@FXML public Label accountCurrencyLabel;
|
||||||
@FXML public Label accountCreatedAtLabel;
|
@FXML public Label accountCreatedAtLabel;
|
||||||
@FXML public Label accountBalanceLabel;
|
@FXML public Label accountBalanceLabel;
|
||||||
@FXML public BooleanProperty accountArchivedProperty = new SimpleBooleanProperty(false);
|
@FXML public PropertiesPane descriptionPane;
|
||||||
|
@FXML public Text accountDescriptionText;
|
||||||
|
|
||||||
@FXML public AccountHistoryView accountHistory;
|
@FXML public AccountHistoryView accountHistory;
|
||||||
|
|
||||||
|
@ -44,11 +49,21 @@ public class AccountViewController implements RouteSelectionListener {
|
||||||
@FXML public Button balanceCheckerButton;
|
@FXML public Button balanceCheckerButton;
|
||||||
|
|
||||||
@FXML public void initialize() {
|
@FXML public void initialize() {
|
||||||
|
titleLabel.textProperty().bind(accountProperty.map(a -> "Account #" + a.id));
|
||||||
|
accountNameLabel.textProperty().bind(accountProperty.map(Account::getName));
|
||||||
|
accountNumberLabel.textProperty().bind(accountProperty.map(Account::getAccountNumber));
|
||||||
|
accountCurrencyLabel.textProperty().bind(accountProperty.map(a -> a.getCurrency().getDisplayName()));
|
||||||
|
accountCreatedAtLabel.textProperty().bind(accountProperty.map(a -> DateUtil.formatUTCAsLocalWithZone(a.getCreatedAt())));
|
||||||
|
accountDescriptionText.textProperty().bind(accountProperty.map(Account::getDescription));
|
||||||
|
var hasDescription = accountProperty.map(a -> a.getDescription() != null);
|
||||||
|
BindingUtil.bindManagedAndVisible(descriptionPane, hasDescription);
|
||||||
|
accountBalanceLabel.textProperty().bind(balanceTextProperty);
|
||||||
|
|
||||||
actionsBox.getChildren().forEach(node -> {
|
actionsBox.getChildren().forEach(node -> {
|
||||||
Button button = (Button) node;
|
Button button = (Button) node;
|
||||||
BooleanExpression buttonActive = accountArchivedProperty;
|
ObservableValue<Boolean> buttonActive = accountArchived;
|
||||||
if (button.getText().equalsIgnoreCase("Unarchive")) {
|
if (button.getText().equalsIgnoreCase("Unarchive")) {
|
||||||
buttonActive = buttonActive.not();
|
buttonActive = BooleanExpression.booleanExpression(buttonActive).not();
|
||||||
}
|
}
|
||||||
button.disableProperty().bind(buttonActive);
|
button.disableProperty().bind(buttonActive);
|
||||||
button.managedProperty().bind(button.visibleProperty());
|
button.managedProperty().bind(button.visibleProperty());
|
||||||
|
@ -66,41 +81,42 @@ public class AccountViewController implements RouteSelectionListener {
|
||||||
.toInstant();
|
.toInstant();
|
||||||
Profile.getCurrent().dataSource().mapRepoAsync(
|
Profile.getCurrent().dataSource().mapRepoAsync(
|
||||||
AccountRepository.class,
|
AccountRepository.class,
|
||||||
repo -> repo.deriveBalance(account.id, timestamp)
|
repo -> repo.deriveBalance(getAccount().id, timestamp)
|
||||||
).thenAccept(balance -> Platform.runLater(() -> {
|
).thenAccept(balance -> Platform.runLater(() -> {
|
||||||
String msg = String.format(
|
String msg = String.format(
|
||||||
"Your balance as of %s is %s, according to Perfin's data.",
|
"Your balance as of %s is %s, according to Perfin's data.",
|
||||||
date,
|
date,
|
||||||
CurrencyUtil.formatMoney(new MoneyValue(balance, account.getCurrency()))
|
CurrencyUtil.formatMoney(new MoneyValue(balance, getAccount().getCurrency()))
|
||||||
);
|
);
|
||||||
Popups.message(balanceCheckerButton, msg);
|
Popups.message(balanceCheckerButton, msg);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
accountProperty.addListener((observable, oldValue, newValue) -> {
|
||||||
|
accountHistory.clear();
|
||||||
|
if (newValue == null) {
|
||||||
|
balanceTextProperty.set(null);
|
||||||
|
} else {
|
||||||
|
accountHistory.setAccountId(newValue.id);
|
||||||
|
accountHistory.loadMoreHistory();
|
||||||
|
Profile.getCurrent().dataSource().getAccountBalanceText(newValue)
|
||||||
|
.thenAccept(s -> Platform.runLater(() -> balanceTextProperty.set(s)));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRouteSelected(Object context) {
|
public void onRouteSelected(Object context) {
|
||||||
account = (Account) context;
|
this.accountProperty.set((Account) context);
|
||||||
accountArchivedProperty.set(account.isArchived());
|
|
||||||
titleLabel.setText("Account #" + account.id);
|
|
||||||
accountNameLabel.setText(account.getName());
|
|
||||||
accountNumberLabel.setText(account.getAccountNumber());
|
|
||||||
accountCurrencyLabel.setText(account.getCurrency().getDisplayName());
|
|
||||||
accountCreatedAtLabel.setText(DateUtil.formatUTCAsLocalWithZone(account.getCreatedAt()));
|
|
||||||
Profile.getCurrent().dataSource().getAccountBalanceText(account)
|
|
||||||
.thenAccept(accountBalanceLabel::setText);
|
|
||||||
accountHistory.clear();
|
|
||||||
accountHistory.setAccountId(account.id);
|
|
||||||
accountHistory.loadMoreHistory();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void goToEditPage() {
|
public void goToEditPage() {
|
||||||
router.navigate("edit-account", account);
|
router.navigate("edit-account", getAccount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML public void goToCreateBalanceRecord() {
|
@FXML public void goToCreateBalanceRecord() {
|
||||||
router.navigate("create-balance-record", account);
|
router.navigate("create-balance-record", getAccount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -114,7 +130,7 @@ public class AccountViewController implements RouteSelectionListener {
|
||||||
"later if you need to."
|
"later if you need to."
|
||||||
);
|
);
|
||||||
if (confirmResult) {
|
if (confirmResult) {
|
||||||
Profile.getCurrent().dataSource().useRepo(AccountRepository.class, repo -> repo.archive(account.id));
|
Profile.getCurrent().dataSource().useRepo(AccountRepository.class, repo -> repo.archive(getAccount().id));
|
||||||
router.replace("accounts");
|
router.replace("accounts");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +142,7 @@ public class AccountViewController implements RouteSelectionListener {
|
||||||
"status?"
|
"status?"
|
||||||
);
|
);
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
Profile.getCurrent().dataSource().useRepo(AccountRepository.class, repo -> repo.unarchive(account.id));
|
Profile.getCurrent().dataSource().useRepo(AccountRepository.class, repo -> repo.unarchive(getAccount().id));
|
||||||
router.replace("accounts");
|
router.replace("accounts");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,8 +158,12 @@ public class AccountViewController implements RouteSelectionListener {
|
||||||
"want to hide it."
|
"want to hide it."
|
||||||
);
|
);
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
Profile.getCurrent().dataSource().useRepo(AccountRepository.class, repo -> repo.delete(account));
|
Profile.getCurrent().dataSource().useRepo(AccountRepository.class, repo -> repo.delete(getAccount()));
|
||||||
router.replace("accounts");
|
router.replace("accounts");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Account getAccount() {
|
||||||
|
return accountProperty.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,20 +33,14 @@ public class EditAccountController implements RouteSelectionListener {
|
||||||
private Account account;
|
private Account account;
|
||||||
private final BooleanProperty creatingNewAccount = new SimpleBooleanProperty(false);
|
private final BooleanProperty creatingNewAccount = new SimpleBooleanProperty(false);
|
||||||
|
|
||||||
@FXML
|
@FXML public Label titleLabel;
|
||||||
public Label titleLabel;
|
@FXML public TextField accountNameField;
|
||||||
@FXML
|
@FXML public TextField accountNumberField;
|
||||||
public TextField accountNameField;
|
@FXML public ComboBox<Currency> accountCurrencyComboBox;
|
||||||
@FXML
|
@FXML public ChoiceBox<AccountType> accountTypeChoiceBox;
|
||||||
public TextField accountNumberField;
|
@FXML public TextArea descriptionField;
|
||||||
@FXML
|
@FXML public PropertiesPane initialBalanceContent;
|
||||||
public ComboBox<Currency> accountCurrencyComboBox;
|
@FXML public TextField initialBalanceField;
|
||||||
@FXML
|
|
||||||
public ChoiceBox<AccountType> accountTypeChoiceBox;
|
|
||||||
@FXML
|
|
||||||
public PropertiesPane initialBalanceContent;
|
|
||||||
@FXML
|
|
||||||
public TextField initialBalanceField;
|
|
||||||
|
|
||||||
@FXML public Button saveButton;
|
@FXML public Button saveButton;
|
||||||
|
|
||||||
|
@ -66,8 +60,12 @@ public class EditAccountController implements RouteSelectionListener {
|
||||||
new CurrencyAmountValidator(() -> accountCurrencyComboBox.getValue(), true, false)
|
new CurrencyAmountValidator(() -> accountCurrencyComboBox.getValue(), true, false)
|
||||||
).attachToTextField(initialBalanceField, accountCurrencyComboBox.valueProperty());
|
).attachToTextField(initialBalanceField, accountCurrencyComboBox.valueProperty());
|
||||||
|
|
||||||
|
var descriptionValid = new ValidationApplier<>(new PredicateValidator<String>()
|
||||||
|
.addPredicate(s -> s == null || s.strip().length() <= Account.DESCRIPTION_MAX_LENGTH, "Description is too long.")
|
||||||
|
).attach(descriptionField, descriptionField.textProperty());
|
||||||
|
|
||||||
// Combine validity of all fields for an expression that determines if the whole form is valid.
|
// Combine validity of all fields for an expression that determines if the whole form is valid.
|
||||||
BooleanExpression formValid = nameValid.and(numberValid).and(balanceValid.or(creatingNewAccount.not()));
|
BooleanExpression formValid = nameValid.and(numberValid).and(balanceValid.or(creatingNewAccount.not())).and(descriptionValid);
|
||||||
saveButton.disableProperty().bind(formValid.not());
|
saveButton.disableProperty().bind(formValid.not());
|
||||||
|
|
||||||
List<Currency> priorityCurrencies = Stream.of("USD", "EUR", "GBP", "CAD", "AUD")
|
List<Currency> priorityCurrencies = Stream.of("USD", "EUR", "GBP", "CAD", "AUD")
|
||||||
|
@ -111,6 +109,11 @@ public class EditAccountController implements RouteSelectionListener {
|
||||||
String number = accountNumberField.getText().strip();
|
String number = accountNumberField.getText().strip();
|
||||||
AccountType type = accountTypeChoiceBox.getValue();
|
AccountType type = accountTypeChoiceBox.getValue();
|
||||||
Currency currency = accountCurrencyComboBox.getValue();
|
Currency currency = accountCurrencyComboBox.getValue();
|
||||||
|
String description = descriptionField.getText();
|
||||||
|
if (description != null) {
|
||||||
|
description = description.strip();
|
||||||
|
if (description.isBlank()) description = null;
|
||||||
|
}
|
||||||
try (
|
try (
|
||||||
var accountRepo = Profile.getCurrent().dataSource().getAccountRepository();
|
var accountRepo = Profile.getCurrent().dataSource().getAccountRepository();
|
||||||
var balanceRepo = Profile.getCurrent().dataSource().getBalanceRecordRepository()
|
var balanceRepo = Profile.getCurrent().dataSource().getBalanceRecordRepository()
|
||||||
|
@ -128,14 +131,14 @@ public class EditAccountController implements RouteSelectionListener {
|
||||||
);
|
);
|
||||||
boolean success = Popups.confirm(accountNameField, prompt);
|
boolean success = Popups.confirm(accountNameField, prompt);
|
||||||
if (success) {
|
if (success) {
|
||||||
long id = accountRepo.insert(type, number, name, currency);
|
long id = accountRepo.insert(type, number, name, currency, description);
|
||||||
balanceRepo.insert(LocalDateTime.now(ZoneOffset.UTC), id, initialBalance, currency, attachments);
|
balanceRepo.insert(LocalDateTime.now(ZoneOffset.UTC), id, initialBalance, currency, attachments);
|
||||||
// Once we create the new account, go to the account.
|
// Once we create the new account, go to the account.
|
||||||
Account newAccount = accountRepo.findById(id).orElseThrow();
|
Account newAccount = accountRepo.findById(id).orElseThrow();
|
||||||
router.replace("account", newAccount);
|
router.replace("account", newAccount);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
accountRepo.update(account.id, type, number, name, currency);
|
accountRepo.update(account.id, type, number, name, currency, description);
|
||||||
Account updatedAccount = accountRepo.findById(account.id).orElseThrow();
|
Account updatedAccount = accountRepo.findById(account.id).orElseThrow();
|
||||||
router.replace("account", updatedAccount);
|
router.replace("account", updatedAccount);
|
||||||
}
|
}
|
||||||
|
@ -157,11 +160,13 @@ public class EditAccountController implements RouteSelectionListener {
|
||||||
accountTypeChoiceBox.getSelectionModel().selectFirst();
|
accountTypeChoiceBox.getSelectionModel().selectFirst();
|
||||||
accountCurrencyComboBox.getSelectionModel().select(Currency.getInstance("USD"));
|
accountCurrencyComboBox.getSelectionModel().select(Currency.getInstance("USD"));
|
||||||
initialBalanceField.setText(String.format("%.02f", 0f));
|
initialBalanceField.setText(String.format("%.02f", 0f));
|
||||||
|
descriptionField.setText(null);
|
||||||
} else {
|
} else {
|
||||||
accountNameField.setText(account.getName());
|
accountNameField.setText(account.getName());
|
||||||
accountNumberField.setText(account.getAccountNumber());
|
accountNumberField.setText(account.getAccountNumber());
|
||||||
accountTypeChoiceBox.getSelectionModel().select(account.getType());
|
accountTypeChoiceBox.getSelectionModel().select(account.getType());
|
||||||
accountCurrencyComboBox.getSelectionModel().select(account.getCurrency());
|
accountCurrencyComboBox.getSelectionModel().select(account.getCurrency());
|
||||||
|
descriptionField.setText(account.getDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,14 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface AccountRepository extends Repository, AutoCloseable {
|
public interface AccountRepository extends Repository, AutoCloseable {
|
||||||
long insert(AccountType type, String accountNumber, String name, Currency currency);
|
long insert(AccountType type, String accountNumber, String name, Currency currency, String description);
|
||||||
Page<Account> findAll(PageRequest pagination);
|
Page<Account> findAll(PageRequest pagination);
|
||||||
List<Account> findAllOrderedByRecentHistory();
|
List<Account> findAllOrderedByRecentHistory();
|
||||||
List<Account> findTopNOrderedByRecentHistory(int n);
|
List<Account> findTopNOrderedByRecentHistory(int n);
|
||||||
List<Account> findTopNRecentlyActive(int n, int daysSinceLastActive);
|
List<Account> findTopNRecentlyActive(int n, int daysSinceLastActive);
|
||||||
List<Account> findAllByCurrency(Currency currency);
|
List<Account> findAllByCurrency(Currency currency);
|
||||||
Optional<Account> findById(long id);
|
Optional<Account> findById(long id);
|
||||||
void update(long accountId, AccountType type, String accountNumber, String name, Currency currency);
|
void update(long accountId, AccountType type, String accountNumber, String name, Currency currency, String description);
|
||||||
void delete(Account account);
|
void delete(Account account);
|
||||||
void archive(long accountId);
|
void archive(long accountId);
|
||||||
void unarchive(long accountId);
|
void unarchive(long accountId);
|
||||||
|
|
|
@ -23,18 +23,18 @@ public record JdbcAccountRepository(Connection conn, Path contentDir) implements
|
||||||
private static final Logger log = LoggerFactory.getLogger(JdbcAccountRepository.class);
|
private static final Logger log = LoggerFactory.getLogger(JdbcAccountRepository.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long insert(AccountType type, String accountNumber, String name, Currency currency) {
|
public long insert(AccountType type, String accountNumber, String name, Currency currency, String description) {
|
||||||
return DbUtil.doTransaction(conn, () -> {
|
return DbUtil.doTransaction(conn, () -> {
|
||||||
|
|
||||||
long accountId = DbUtil.insertOne(
|
long accountId = DbUtil.insertOne(
|
||||||
conn,
|
conn,
|
||||||
"INSERT INTO account (created_at, account_type, account_number, name, currency) VALUES (?, ?, ?, ?, ?)",
|
"INSERT INTO account (created_at, account_type, account_number, name, currency, description) VALUES (?, ?, ?, ?, ?, ?)",
|
||||||
List.of(
|
|
||||||
DbUtil.timestampFromUtcNow(),
|
DbUtil.timestampFromUtcNow(),
|
||||||
type.name(),
|
type.name(),
|
||||||
accountNumber,
|
accountNumber,
|
||||||
name,
|
name,
|
||||||
currency.getCurrencyCode()
|
currency.getCurrencyCode(),
|
||||||
)
|
description
|
||||||
);
|
);
|
||||||
// Insert a history item indicating the creation of the account.
|
// Insert a history item indicating the creation of the account.
|
||||||
HistoryRepository historyRepo = new JdbcHistoryRepository(conn);
|
HistoryRepository historyRepo = new JdbcHistoryRepository(conn);
|
||||||
|
@ -210,7 +210,7 @@ public record JdbcAccountRepository(Connection conn, Path contentDir) implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(long accountId, AccountType type, String accountNumber, String name, Currency currency) {
|
public void update(long accountId, AccountType type, String accountNumber, String name, Currency currency, String description) {
|
||||||
DbUtil.doTransaction(conn, () -> {
|
DbUtil.doTransaction(conn, () -> {
|
||||||
Account account = findById(accountId).orElse(null);
|
Account account = findById(accountId).orElse(null);
|
||||||
if (account == null) return;
|
if (account == null) return;
|
||||||
|
@ -231,6 +231,10 @@ public record JdbcAccountRepository(Connection conn, Path contentDir) implements
|
||||||
DbUtil.updateOne(conn, "UPDATE account SET currency = ? WHERE id = ?", currency.getCurrencyCode(), accountId);
|
DbUtil.updateOne(conn, "UPDATE account SET currency = ? WHERE id = ?", currency.getCurrencyCode(), accountId);
|
||||||
updateMessages.add(String.format("Updated account currency from %s to %s.", account.getCurrency(), currency));
|
updateMessages.add(String.format("Updated account currency from %s to %s.", account.getCurrency(), currency));
|
||||||
}
|
}
|
||||||
|
if (!Objects.equals(account.getDescription(), description)) {
|
||||||
|
DbUtil.updateOne(conn, "UPDATE account SET description = ? WHERE id = ?", description, accountId);
|
||||||
|
updateMessages.add("Updated account's description.");
|
||||||
|
}
|
||||||
if (!updateMessages.isEmpty()) {
|
if (!updateMessages.isEmpty()) {
|
||||||
var historyRepo = new JdbcHistoryRepository(conn);
|
var historyRepo = new JdbcHistoryRepository(conn);
|
||||||
long historyId = historyRepo.getOrCreateHistoryForAccount(accountId);
|
long historyId = historyRepo.getOrCreateHistoryForAccount(accountId);
|
||||||
|
|
|
@ -28,7 +28,13 @@ public final class DbUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setArgs(PreparedStatement stmt, Object... args) {
|
public static void setArgs(PreparedStatement stmt, Object... args) {
|
||||||
setArgs(stmt, List.of(args));
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
try {
|
||||||
|
stmt.setObject(i + 1, args[i]);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new UncheckedSqlException("Failed to set parameter " + (i + 1) + " to " + args[i], e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getGeneratedId(PreparedStatement stmt) {
|
public static long getGeneratedId(PreparedStatement stmt) {
|
||||||
|
@ -107,6 +113,11 @@ public final class DbUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateOne(Connection conn, String query, List<Object> args) {
|
public static void updateOne(Connection conn, String query, List<Object> args) {
|
||||||
|
Object[] argsArray = args.toArray();
|
||||||
|
updateOne(conn, query, argsArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateOne(Connection conn, String query, Object... args) {
|
||||||
try (var stmt = conn.prepareStatement(query)) {
|
try (var stmt = conn.prepareStatement(query)) {
|
||||||
setArgs(stmt, args);
|
setArgs(stmt, args);
|
||||||
int updateCount = stmt.executeUpdate();
|
int updateCount = stmt.executeUpdate();
|
||||||
|
@ -116,11 +127,12 @@ public final class DbUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateOne(Connection conn, String query, Object... args) {
|
public static long insertOne(Connection conn, String query, List<Object> args) {
|
||||||
updateOne(conn, query, List.of(args));
|
Object[] argsArray = args.toArray();
|
||||||
|
return insertOne(conn, query, argsArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long insertOne(Connection conn, String query, List<Object> args) {
|
public static long insertOne(Connection conn, String query, Object... args) {
|
||||||
try (var stmt = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {
|
try (var stmt = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {
|
||||||
setArgs(stmt, args);
|
setArgs(stmt, args);
|
||||||
int result = stmt.executeUpdate();
|
int result = stmt.executeUpdate();
|
||||||
|
@ -131,10 +143,6 @@ public final class DbUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long insertOne(Connection conn, String query, Object... args) {
|
|
||||||
return insertOne(conn, query, List.of(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Timestamp timestampFromUtcLDT(LocalDateTime utc) {
|
public static Timestamp timestampFromUtcLDT(LocalDateTime utc) {
|
||||||
return Timestamp.from(utc.toInstant(ZoneOffset.UTC));
|
return Timestamp.from(utc.toInstant(ZoneOffset.UTC));
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,11 @@
|
||||||
</PropertiesPane>
|
</PropertiesPane>
|
||||||
</FlowPane>
|
</FlowPane>
|
||||||
|
|
||||||
|
<PropertiesPane vgap="5" hgap="5" fx:id="descriptionPane">
|
||||||
|
<Label text="Description" styleClass="bold-text" labelFor="${accountDescriptionText}"/>
|
||||||
|
<TextFlow maxWidth="500"><Text fx:id="accountDescriptionText"/></TextFlow>
|
||||||
|
</PropertiesPane>
|
||||||
|
|
||||||
<!-- Action buttons -->
|
<!-- Action buttons -->
|
||||||
<HBox fx:id="actionsBox" styleClass="std-padding,std-spacing,small-font">
|
<HBox fx:id="actionsBox" styleClass="std-padding,std-spacing,small-font">
|
||||||
<Button text="Edit" onAction="#goToEditPage"/>
|
<Button text="Edit" onAction="#goToEditPage"/>
|
||||||
|
|
|
@ -32,6 +32,13 @@
|
||||||
|
|
||||||
<Label text="Account Type" styleClass="bold-text"/>
|
<Label text="Account Type" styleClass="bold-text"/>
|
||||||
<ChoiceBox fx:id="accountTypeChoiceBox"/>
|
<ChoiceBox fx:id="accountTypeChoiceBox"/>
|
||||||
|
|
||||||
|
<Label text="Description" styleClass="bold-text"/>
|
||||||
|
<TextArea
|
||||||
|
fx:id="descriptionField"
|
||||||
|
wrapText="true"
|
||||||
|
style="-fx-pref-height: 100px;-fx-min-height: 100px;"
|
||||||
|
/>
|
||||||
</PropertiesPane>
|
</PropertiesPane>
|
||||||
|
|
||||||
<!-- Initial balance content that's only visible when creating a new account. -->
|
<!-- Initial balance content that's only visible when creating a new account. -->
|
||||||
|
|
Loading…
Reference in New Issue