fix: Double to BigDecimal
This commit is contained in:
parent
b11607088a
commit
f42dcce74b
15 changed files with 93 additions and 57 deletions
|
@ -7,6 +7,8 @@ import lombok.AllArgsConstructor;
|
|||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
|
@ -18,6 +20,6 @@ public class CurrencyEntity {
|
|||
String pesel;
|
||||
@Id
|
||||
String symbol;
|
||||
Double amount;
|
||||
BigDecimal amount;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package eu.ztsh.wymiana.model;
|
||||
|
||||
public record Currency(String symbol, double amount) {
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public record Currency(String symbol, BigDecimal amount) {
|
||||
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ public class CurrencyService {
|
|||
}
|
||||
var exchanged = performExchange(from,
|
||||
Optional.ofNullable(user.currencies().get(request.to().toUpperCase())).orElse(create(request.to())),
|
||||
Optional.ofNullable(request.toSell()).orElse(0D),
|
||||
Optional.ofNullable(request.toBuy()).orElse(0D));
|
||||
Optional.ofNullable(request.toSell()).orElse(BigDecimal.ZERO),
|
||||
Optional.ofNullable(request.toBuy()).orElse(BigDecimal.ZERO));
|
||||
user.currencies().putAll(exchanged);
|
||||
return userService.update(user);
|
||||
})
|
||||
|
@ -55,32 +55,36 @@ public class CurrencyService {
|
|||
|
||||
private Currency create(String symbol) {
|
||||
// TODO: check if supported - now limited to PLN <-> USD
|
||||
return new Currency(symbol.toUpperCase(), 0D);
|
||||
return new Currency(symbol.toUpperCase(), BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
private Map<String, Currency> performExchange(Currency from, Currency to, double toSell, double toBuy) {
|
||||
double exchangeRate;
|
||||
double neededFromAmount;
|
||||
double requestedToAmount;
|
||||
private Map<String, Currency> performExchange(Currency from, Currency to, BigDecimal toSell, BigDecimal toBuy) {
|
||||
BigDecimal exchangeRate;
|
||||
BigDecimal neededFromAmount;
|
||||
BigDecimal requestedToAmount;
|
||||
if (from.symbol().equalsIgnoreCase("PLN")) {
|
||||
exchangeRate = nbpService.getSellRate(to.symbol());
|
||||
neededFromAmount = round(toBuy != 0 ? toBuy * exchangeRate : toSell);
|
||||
requestedToAmount = round(toBuy != 0 ? toBuy : toSell / exchangeRate);
|
||||
neededFromAmount = round(toBuy.signum() != 0 ? toBuy.multiply(exchangeRate) : toSell);
|
||||
requestedToAmount = round(toBuy.signum() != 0 ? toBuy : divide(toSell, exchangeRate));
|
||||
} else {
|
||||
exchangeRate = nbpService.getBuyRate(from.symbol());
|
||||
neededFromAmount = round(toBuy != 0 ? toBuy / exchangeRate : toSell);
|
||||
requestedToAmount = round(toBuy != 0 ? toBuy : toSell * exchangeRate);
|
||||
neededFromAmount = round(toBuy.signum() != 0 ? divide(toBuy, exchangeRate) : toSell);
|
||||
requestedToAmount = round(toBuy.signum() != 0 ? toBuy : toSell.multiply(exchangeRate));
|
||||
}
|
||||
if (neededFromAmount > from.amount()) {
|
||||
if (neededFromAmount.compareTo(from.amount()) > 0) {
|
||||
throw new InsufficientFundsException();
|
||||
}
|
||||
var newFrom = new Currency(from.symbol(), from.amount() - neededFromAmount);
|
||||
var newTo = new Currency(to.symbol(), to.amount() + requestedToAmount);
|
||||
var newFrom = new Currency(from.symbol(), from.amount().subtract(neededFromAmount));
|
||||
var newTo = new Currency(to.symbol(), to.amount().add(requestedToAmount));
|
||||
return Stream.of(newFrom, newTo).collect(Collectors.toMap(Currency::symbol, currency -> currency));
|
||||
}
|
||||
|
||||
private double round(double input) {
|
||||
return BigDecimal.valueOf(input).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
private BigDecimal round(BigDecimal input) {
|
||||
return input.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private BigDecimal divide(BigDecimal input, BigDecimal division) {
|
||||
return input.setScale(2, RoundingMode.HALF_UP).divide(division, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.springframework.http.HttpStatusCode;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Clock;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
|
@ -30,11 +31,11 @@ public class NbpService {
|
|||
|
||||
private final ConcurrentMap<String, RatesCache> cache = new ConcurrentHashMap<>(1);
|
||||
|
||||
public double getSellRate(String currency) {
|
||||
public BigDecimal getSellRate(String currency) {
|
||||
return getCurrency(currency.toUpperCase()).sell();
|
||||
}
|
||||
|
||||
public double getBuyRate(String currency) {
|
||||
public BigDecimal getBuyRate(String currency) {
|
||||
return getCurrency(currency.toUpperCase()).buy();
|
||||
}
|
||||
|
||||
|
@ -43,7 +44,7 @@ public class NbpService {
|
|||
var cacheObject = cache.get(currency);
|
||||
if (cacheObject == null || cacheObject.date().isBefore(today)) {
|
||||
var fresh = fetchData(currency, dtf.format(today));
|
||||
var rate = fresh.getRates().get(0);
|
||||
var rate = fresh.getRates().getFirst();
|
||||
cacheObject = new RatesCache(
|
||||
LocalDate.parse(rate.getEffectiveDate(), dtf),
|
||||
rate.getBid(),
|
||||
|
@ -82,7 +83,7 @@ public class NbpService {
|
|||
|| today.getDayOfWeek() == DayOfWeek.SUNDAY;
|
||||
}
|
||||
|
||||
private record RatesCache(LocalDate date, double buy, double sell) {
|
||||
private record RatesCache(LocalDate date, BigDecimal buy, BigDecimal sell) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ public class UserMapper {
|
|||
|
||||
public static UserEntity requestToEntity(UserCreateRequest request) {
|
||||
return new UserEntity(request.pesel(), request.name(), request.surname(),
|
||||
List.of(new CurrencyEntity(request.pesel(), "PLN", request.pln())));
|
||||
List.of(new CurrencyEntity(request.pesel(), "PLN", request.initial())));
|
||||
}
|
||||
|
||||
private UserMapper() {
|
||||
|
|
|
@ -18,8 +18,8 @@ public class ValidExchangeRequestValidator implements
|
|||
return (request.from() != null && !request.from().equals(request.to()))
|
||||
&& !((request.toBuy() == null && request.toSell() == null)
|
||||
|| (request.toBuy() != null && request.toSell() != null))
|
||||
&& ((request.toBuy() != null && request.toBuy() >= 0)
|
||||
|| (request.toSell() != null && request.toSell() >= 0));
|
||||
&& ((request.toBuy() != null && request.toBuy().signum() >= 0)
|
||||
|| (request.toSell() != null && request.toSell().signum() >= 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,14 +5,16 @@ import jakarta.validation.constraints.NotNull;
|
|||
import lombok.Builder;
|
||||
import org.hibernate.validator.constraints.pl.PESEL;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Builder
|
||||
@ValidExchangeRequest
|
||||
public record CurrencyExchangeRequest(
|
||||
@PESEL String pesel,
|
||||
@NotNull String from,
|
||||
@NotNull String to,
|
||||
Double toBuy,
|
||||
Double toSell
|
||||
BigDecimal toBuy,
|
||||
BigDecimal toSell
|
||||
) {
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ import jakarta.validation.constraints.NotNull;
|
|||
import lombok.Builder;
|
||||
import org.hibernate.validator.constraints.pl.PESEL;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Builder
|
||||
public record UserCreateRequest(
|
||||
@NotNull String name,
|
||||
@NotNull String surname,
|
||||
@PESEL @Adult String pesel,
|
||||
@Min(0) double pln) {
|
||||
@Min(0) BigDecimal initial) {
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue