Added better currency and exchange information.
This commit is contained in:
parent
c643475f45
commit
5ffe9b3a84
|
@ -5,6 +5,9 @@ import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,5 +34,11 @@ public class Account {
|
||||||
@OneToMany(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
|
@OneToMany(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
private Set<Balance> balances;
|
private Set<Balance> balances;
|
||||||
|
|
||||||
|
public Map<Currency, BigDecimal> getMappedBalances() {
|
||||||
|
Map<Currency, BigDecimal> b = new HashMap<>();
|
||||||
|
for (var bal : getBalances()) {
|
||||||
|
b.put(bal.getCurrency(), bal.getAmount());
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,6 @@ public class Balance {
|
||||||
@ManyToOne(optional = false, fetch = FetchType.EAGER)
|
@ManyToOne(optional = false, fetch = FetchType.EAGER)
|
||||||
private Currency currency;
|
private Currency currency;
|
||||||
|
|
||||||
@Column(nullable = false, precision = 24, scale = 4)
|
@Column(nullable = false, precision = 24, scale = 10)
|
||||||
private BigDecimal amount;
|
private BigDecimal amount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package nl.andrewl.coyotecredit.model;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a type of currency. This can be an actual fiat currency, or
|
* Represents a type of currency. This can be an actual fiat currency, or
|
||||||
|
@ -10,6 +11,7 @@ import javax.persistence.*;
|
||||||
* exchange.
|
* exchange.
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"identifier", "type"}))
|
||||||
@Getter
|
@Getter
|
||||||
public class Currency {
|
public class Currency {
|
||||||
@Id
|
@Id
|
||||||
|
@ -19,9 +21,28 @@ public class Currency {
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String identifier;
|
private String identifier;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private CurrencyType type;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private float minDenomination = 0.01f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (!(other instanceof Currency c)) return false;
|
||||||
|
if (c.getId() != null && this.getId() != null) return this.getId().equals(c.getId());
|
||||||
|
return this.identifier.equals(c.getIdentifier()) &&
|
||||||
|
this.type.equals(c.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.identifier, this.type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package nl.andrewl.coyotecredit.model;
|
||||||
|
|
||||||
|
public enum CurrencyType {
|
||||||
|
FIAT,
|
||||||
|
CRYPTO,
|
||||||
|
STOCK
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package nl.andrewl.coyotecredit.model;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,11 +22,15 @@ public class Exchange {
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
@OneToMany(mappedBy = "exchange")
|
||||||
@JoinTable(
|
private Set<ExchangePair> currencyPairs;
|
||||||
name = "exchange_supported_currency",
|
|
||||||
joinColumns = @JoinColumn(name = "currency_id"),
|
public Set<Currency> getSupportedCurrencies() {
|
||||||
inverseJoinColumns = @JoinColumn(name = "exchange_id")
|
Set<Currency> currencies = new HashSet<>();
|
||||||
)
|
for (var pair : getCurrencyPairs()) {
|
||||||
private Set<Currency> supportedCurrencies;
|
currencies.add(pair.getFromCurrency());
|
||||||
|
currencies.add(pair.getToCurrency());
|
||||||
|
}
|
||||||
|
return currencies;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package nl.andrewl.coyotecredit.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a pair of currencies that can be exchanged at a set exchange rate.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"from_currency_id", "to_currency_id", "exchange_id"}))
|
||||||
|
@Getter
|
||||||
|
public class ExchangePair {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private Exchange exchange;
|
||||||
|
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private Currency fromCurrency;
|
||||||
|
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private Currency toCurrency;
|
||||||
|
|
||||||
|
@Column(nullable = false, precision = 24, scale = 10)
|
||||||
|
private BigDecimal exchangeRate = new BigDecimal("1.0");
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package nl.andrewl.coyotecredit.service;
|
package nl.andrewl.coyotecredit.service;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import nl.andrewl.coyotecredit.dao.AccountRepository;
|
import nl.andrewl.coyotecredit.dao.AccountRepository;
|
||||||
import nl.andrewl.coyotecredit.model.Account;
|
import nl.andrewl.coyotecredit.model.Account;
|
||||||
|
@ -9,6 +10,7 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -29,13 +31,36 @@ public class AccountService {
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class FullAccountData {
|
||||||
|
public long id;
|
||||||
|
public String number;
|
||||||
|
public String exchangeName;
|
||||||
|
public List<BalanceData> balances;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class BalanceData {
|
||||||
|
public String currencyIdentifier;
|
||||||
|
public String amount;
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public AccountData getAccountData(User user, long accountId) {
|
public FullAccountData getAccountData(User user, long accountId) {
|
||||||
Account account = accountRepository.findById(accountId)
|
Account account = accountRepository.findById(accountId)
|
||||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
|
|
||||||
if (!account.getUser().getId().equals(user.getId())) {
|
if (!account.getUser().getId().equals(user.getId())) {
|
||||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
|
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return new AccountData(account.getId(), account.getNumber(), account.getExchange().getName());
|
FullAccountData d = new FullAccountData();
|
||||||
|
d.id = account.getId();
|
||||||
|
d.number = account.getNumber();
|
||||||
|
d.exchangeName = account.getExchange().getName();
|
||||||
|
List<BalanceData> balanceData = new ArrayList<>();
|
||||||
|
for (var bal : account.getBalances()) {
|
||||||
|
balanceData.add(new BalanceData(bal.getCurrency().getIdentifier(), bal.getAmount().toPlainString()));
|
||||||
|
}
|
||||||
|
d.balances = balanceData;
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html
|
||||||
|
lang="en"
|
||||||
|
xmlns:th="http://www.thymeleaf.org"
|
||||||
|
>
|
||||||
|
<head>
|
||||||
|
<title>CC - Account</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Account <span th:text="${account.number}"></span></h1>
|
||||||
|
|
||||||
|
<h3>Balance</h3>
|
||||||
|
<ul>
|
||||||
|
<li th:each="balance : ${account.balances}">
|
||||||
|
<span th:text="${balance.currencyIdentifier}"></span> - <span th:text="${balance.amount}"></span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
Loading…
Reference in New Issue