fix: Double to BigDecimal

This commit is contained in:
Piotr Dec 2024-06-10 23:52:47 +02:00
parent b11607088a
commit f42dcce74b
Signed by: stawros
GPG key ID: F89F27AD8F881A91
15 changed files with 93 additions and 57 deletions

View file

@ -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;
}

View file

@ -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) {
}

View file

@ -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);
}
}

View file

@ -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) {
}

View file

@ -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() {

View file

@ -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));
}
}

View file

@ -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
) {
}

View file

@ -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) {
}