Fixed account editing.
This commit is contained in:
		
							parent
							
								
									807259b2a5
								
							
						
					
					
						commit
						abf132ec99
					
				| 
						 | 
				
			
			@ -1,8 +1,10 @@
 | 
			
		|||
package com.andrewlalis.perfin.control;
 | 
			
		||||
 | 
			
		||||
import com.andrewlalis.javafx_scene_router.RouteSelectionListener;
 | 
			
		||||
import com.andrewlalis.perfin.data.util.CurrencyUtil;
 | 
			
		||||
import com.andrewlalis.perfin.model.Account;
 | 
			
		||||
import com.andrewlalis.perfin.model.AccountType;
 | 
			
		||||
import com.andrewlalis.perfin.model.MoneyValue;
 | 
			
		||||
import com.andrewlalis.perfin.model.Profile;
 | 
			
		||||
import com.andrewlalis.perfin.view.component.PropertiesPane;
 | 
			
		||||
import com.andrewlalis.perfin.view.component.validation.ValidationApplier;
 | 
			
		||||
| 
						 | 
				
			
			@ -52,20 +54,20 @@ public class EditAccountController implements RouteSelectionListener {
 | 
			
		|||
    public void initialize() {
 | 
			
		||||
        var nameValid = new ValidationApplier<>(new PredicateValidator<String>()
 | 
			
		||||
                .addTerminalPredicate(s -> s != null && !s.isBlank(), "Name should not be empty.")
 | 
			
		||||
                .addPredicate(s -> s.length() <= 63, "Name is too long.")
 | 
			
		||||
                .addPredicate(s -> s.strip().length() <= 63, "Name is too long.")
 | 
			
		||||
        ).attachToTextField(accountNameField);
 | 
			
		||||
 | 
			
		||||
        var numberValid = new ValidationApplier<>(new PredicateValidator<String>()
 | 
			
		||||
                .addTerminalPredicate(s -> s != null && !s.isBlank(), "Account number should not be empty.")
 | 
			
		||||
                .addPredicate(s -> s.length() <= 255, "Account number is too long.")
 | 
			
		||||
                .addPredicate(s -> s.strip().length() <= 255, "Account number is too long.")
 | 
			
		||||
        ).attachToTextField(accountNumberField);
 | 
			
		||||
 | 
			
		||||
        var balanceValid = new ValidationApplier<>(
 | 
			
		||||
                new CurrencyAmountValidator(() -> accountCurrencyComboBox.getValue(), false, false)
 | 
			
		||||
                new CurrencyAmountValidator(() -> accountCurrencyComboBox.getValue(), true, false)
 | 
			
		||||
        ).attachToTextField(initialBalanceField, accountCurrencyComboBox.valueProperty());
 | 
			
		||||
 | 
			
		||||
        // Combine validity of all fields for an expression that determines if the whole form is valid.
 | 
			
		||||
        BooleanExpression formValid = nameValid.and(numberValid).and(balanceValid);
 | 
			
		||||
        BooleanExpression formValid = nameValid.and(numberValid).and(balanceValid.or(creatingNewAccount.not()));
 | 
			
		||||
        saveButton.disableProperty().bind(formValid.not());
 | 
			
		||||
 | 
			
		||||
        List<Currency> priorityCurrencies = Stream.of("USD", "EUR", "GBP", "CAD", "AUD")
 | 
			
		||||
| 
						 | 
				
			
			@ -104,34 +106,35 @@ public class EditAccountController implements RouteSelectionListener {
 | 
			
		|||
 | 
			
		||||
    @FXML
 | 
			
		||||
    public void save() {
 | 
			
		||||
        String name = accountNameField.getText().strip();
 | 
			
		||||
        String number = accountNumberField.getText().strip();
 | 
			
		||||
        AccountType type = accountTypeChoiceBox.getValue();
 | 
			
		||||
        Currency currency = accountCurrencyComboBox.getValue();
 | 
			
		||||
        try (
 | 
			
		||||
                var accountRepo = Profile.getCurrent().dataSource().getAccountRepository();
 | 
			
		||||
                var balanceRepo = Profile.getCurrent().dataSource().getBalanceRecordRepository()
 | 
			
		||||
        ) {
 | 
			
		||||
            if (creatingNewAccount.get()) {
 | 
			
		||||
                String name = accountNameField.getText().strip();
 | 
			
		||||
                String number = accountNumberField.getText().strip();
 | 
			
		||||
                AccountType type = accountTypeChoiceBox.getValue();
 | 
			
		||||
                Currency currency = accountCurrencyComboBox.getValue();
 | 
			
		||||
                BigDecimal initialBalance = new BigDecimal(initialBalanceField.getText().strip());
 | 
			
		||||
                List<Path> attachments = Collections.emptyList();
 | 
			
		||||
 | 
			
		||||
                boolean success = Popups.confirm(accountNameField, "Are you sure you want to create this account?");
 | 
			
		||||
                String prompt = String.format(
 | 
			
		||||
                        "Are you sure you want to create this account?\nName: %s\nNumber: %s\nType: %s\nInitial Balance: %s",
 | 
			
		||||
                        name,
 | 
			
		||||
                        number,
 | 
			
		||||
                        type.toString(),
 | 
			
		||||
                        CurrencyUtil.formatMoneyWithCurrencyPrefix(new MoneyValue(initialBalance, currency))
 | 
			
		||||
                );
 | 
			
		||||
                boolean success = Popups.confirm(accountNameField, prompt);
 | 
			
		||||
                if (success) {
 | 
			
		||||
                    long id = accountRepo.insert(type, number, name, currency);
 | 
			
		||||
                    balanceRepo.insert(LocalDateTime.now(ZoneOffset.UTC), id, initialBalance, currency, attachments);
 | 
			
		||||
 | 
			
		||||
                    // Once we create the new account, go to the account.
 | 
			
		||||
                    Account newAccount = accountRepo.findById(id).orElseThrow();
 | 
			
		||||
                    router.replace("account", newAccount);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                log.debug("Updating account {}", account.id);
 | 
			
		||||
                account.setName(accountNameField.getText().strip());
 | 
			
		||||
                account.setAccountNumber(accountNumberField.getText().strip());
 | 
			
		||||
                account.setType(accountTypeChoiceBox.getValue());
 | 
			
		||||
                account.setCurrency(accountCurrencyComboBox.getValue());
 | 
			
		||||
                accountRepo.update(account);
 | 
			
		||||
                accountRepo.update(account.id, type, number, name, currency);
 | 
			
		||||
                Account updatedAccount = accountRepo.findById(account.id).orElseThrow();
 | 
			
		||||
                router.replace("account", updatedAccount);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,7 @@ public interface AccountRepository extends Repository, AutoCloseable {
 | 
			
		|||
    List<Account> findTopNRecentlyActive(int n, int daysSinceLastActive);
 | 
			
		||||
    List<Account> findAllByCurrency(Currency currency);
 | 
			
		||||
    Optional<Account> findById(long id);
 | 
			
		||||
    void updateName(long id, String name);
 | 
			
		||||
    void update(Account account);
 | 
			
		||||
    void update(long accountId, AccountType type, String accountNumber, String name, Currency currency);
 | 
			
		||||
    void delete(Account account);
 | 
			
		||||
    void archive(long accountId);
 | 
			
		||||
    void unarchive(long accountId);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,11 +113,6 @@ public record JdbcAccountRepository(Connection conn, Path contentDir) implements
 | 
			
		|||
        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 = ? AND NOT archived", List.of(name, id));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BigDecimal deriveBalance(long accountId, Instant timestamp) {
 | 
			
		||||
        // First find the account itself, since its properties influence the balance.
 | 
			
		||||
| 
						 | 
				
			
			@ -215,18 +210,33 @@ public record JdbcAccountRepository(Connection conn, Path contentDir) implements
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update(Account account) {
 | 
			
		||||
        DbUtil.updateOne(
 | 
			
		||||
                conn,
 | 
			
		||||
                "UPDATE account SET name = ?, account_number = ?, currency = ?, account_type = ? WHERE id = ?",
 | 
			
		||||
                List.of(
 | 
			
		||||
                        account.getName(),
 | 
			
		||||
                        account.getAccountNumber(),
 | 
			
		||||
                        account.getCurrency().getCurrencyCode(),
 | 
			
		||||
                        account.getType().name(),
 | 
			
		||||
                        account.id
 | 
			
		||||
                )
 | 
			
		||||
        );
 | 
			
		||||
    public void update(long accountId, AccountType type, String accountNumber, String name, Currency currency) {
 | 
			
		||||
        DbUtil.doTransaction(conn, () -> {
 | 
			
		||||
            Account account = findById(accountId).orElse(null);
 | 
			
		||||
            if (account == null) return;
 | 
			
		||||
            List<String> updateMessages = new ArrayList<>();
 | 
			
		||||
            if (account.getType() != type) {
 | 
			
		||||
                DbUtil.updateOne(conn, "UPDATE account SET account_type = ? WHERE id = ?", type, accountId);
 | 
			
		||||
                updateMessages.add(String.format("Updated account type from %s to %s.", account.getType().toString(), type.toString()));
 | 
			
		||||
            }
 | 
			
		||||
            if (!account.getAccountNumber().equals(accountNumber)) {
 | 
			
		||||
                DbUtil.updateOne(conn, "UPDATE account SET account_number = ? WHERE id = ?", accountNumber, accountId);
 | 
			
		||||
                updateMessages.add(String.format("Updated account number from %s to %s.", account.getAccountNumber(), accountNumber));
 | 
			
		||||
            }
 | 
			
		||||
            if (!account.getName().equals(name)) {
 | 
			
		||||
                DbUtil.updateOne(conn, "UPDATE account SET name = ? WHERE id = ?", name, accountId);
 | 
			
		||||
                updateMessages.add(String.format("Updated account name from \"%s\" to \"%s\".", account.getName(), name));
 | 
			
		||||
            }
 | 
			
		||||
            if (account.getCurrency() != currency) {
 | 
			
		||||
                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));
 | 
			
		||||
            }
 | 
			
		||||
            if (!updateMessages.isEmpty()) {
 | 
			
		||||
                var historyRepo = new JdbcHistoryRepository(conn);
 | 
			
		||||
                long historyId = historyRepo.getOrCreateHistoryForAccount(accountId);
 | 
			
		||||
                historyRepo.addTextItem(historyId, String.join("\n", updateMessages));
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,10 +11,10 @@ public class Account extends IdEntity {
 | 
			
		|||
    private final LocalDateTime createdAt;
 | 
			
		||||
    private final boolean archived;
 | 
			
		||||
 | 
			
		||||
    private AccountType type;
 | 
			
		||||
    private String accountNumber;
 | 
			
		||||
    private String name;
 | 
			
		||||
    private Currency currency;
 | 
			
		||||
    private final AccountType type;
 | 
			
		||||
    private final String accountNumber;
 | 
			
		||||
    private final String name;
 | 
			
		||||
    private final Currency currency;
 | 
			
		||||
 | 
			
		||||
    public Account(long id, LocalDateTime createdAt, boolean archived, AccountType type, String accountNumber, String name, Currency currency) {
 | 
			
		||||
        super(id);
 | 
			
		||||
| 
						 | 
				
			
			@ -62,22 +62,6 @@ public class Account extends IdEntity {
 | 
			
		|||
        return currency;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setType(AccountType type) {
 | 
			
		||||
        this.type = type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setAccountNumber(String accountNumber) {
 | 
			
		||||
        this.accountNumber = accountNumber;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setName(String name) {
 | 
			
		||||
        this.name = name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setCurrency(Currency currency) {
 | 
			
		||||
        this.currency = currency;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public LocalDateTime getCreatedAt() {
 | 
			
		||||
        return createdAt;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ public class AccountsModule extends DashboardModule {
 | 
			
		|||
 | 
			
		||||
        Label nameLabel = new Label(account.getName());
 | 
			
		||||
        nameLabel.getStyleClass().addAll("bold-text");
 | 
			
		||||
        Label numberLabel = new Label(account.getAccountNumber());
 | 
			
		||||
        Label numberLabel = new Label(account.getAccountNumberSuffix());
 | 
			
		||||
        numberLabel.getStyleClass().addAll("mono-font");
 | 
			
		||||
        Label typeLabel = new Label(account.getType().toString());
 | 
			
		||||
        typeLabel.getStyleClass().add("bold-text");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue