diff --git a/ramls/acq-models b/ramls/acq-models index 494a65e44..3813e58a5 160000 --- a/ramls/acq-models +++ b/ramls/acq-models @@ -1 +1 @@ -Subproject commit 494a65e44f01d3ad01dcc46947587d81ca955083 +Subproject commit 3813e58a5b219c697b566eb983dabc4cc34284e0 diff --git a/src/main/java/org/folio/service/exchange/CurrencyApiResponseField.java b/src/main/java/org/folio/service/exchange/CurrencyApiResponseField.java new file mode 100644 index 000000000..b1507185b --- /dev/null +++ b/src/main/java/org/folio/service/exchange/CurrencyApiResponseField.java @@ -0,0 +1,13 @@ +package org.folio.service.exchange; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum CurrencyApiResponseField { + DATA("data"), + VALUE("value"); + + private final String value; +} diff --git a/src/main/java/org/folio/service/exchange/FinanceApiExchangeRateProvider.java b/src/main/java/org/folio/service/exchange/FinanceApiExchangeRateProvider.java index 144f629dd..6d17d048c 100644 --- a/src/main/java/org/folio/service/exchange/FinanceApiExchangeRateProvider.java +++ b/src/main/java/org/folio/service/exchange/FinanceApiExchangeRateProvider.java @@ -1,5 +1,6 @@ package org.folio.service.exchange; +import static org.folio.service.exchange.FolioExchangeRateType.FOLIO_CURRENT; import static org.javamoney.moneta.convert.ExchangeRateType.ECB; import static org.javamoney.moneta.convert.ExchangeRateType.IDENTITY; @@ -51,7 +52,7 @@ public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) { } private org.folio.rest.acq.model.finance.ExchangeRate getExchangeRateFromService(ConversionQuery conversionQuery) { - double exchangeRate = MonetaryConversions.getExchangeRateProvider(IDENTITY, ECB) + double exchangeRate = MonetaryConversions.getExchangeRateProvider(IDENTITY, FOLIO_CURRENT, ECB) .getExchangeRate(conversionQuery.getBaseCurrency(), conversionQuery.getCurrency()) .getFactor() .doubleValue(); diff --git a/src/main/java/org/folio/service/exchange/FolioCurrentCurrencyRateProvider.java b/src/main/java/org/folio/service/exchange/FolioCurrentCurrencyRateProvider.java new file mode 100644 index 000000000..54c9b033f --- /dev/null +++ b/src/main/java/org/folio/service/exchange/FolioCurrentCurrencyRateProvider.java @@ -0,0 +1,74 @@ +package org.folio.service.exchange; + +import io.vertx.core.json.JsonObject; +import lombok.SneakyThrows; +import lombok.extern.log4j.Log4j2; +import org.javamoney.moneta.convert.ExchangeRateBuilder; +import org.javamoney.moneta.spi.AbstractRateProvider; +import org.javamoney.moneta.spi.DefaultNumberValue; + +import javax.money.convert.ConversionQuery; +import javax.money.convert.ExchangeRate; +import javax.money.convert.ProviderContext; +import javax.money.convert.ProviderContextBuilder; +import javax.money.convert.RateType; +import java.math.BigDecimal; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.folio.service.exchange.FolioExchangeRateType.FOLIO_CURRENT; + +@Log4j2 +public class FolioCurrentCurrencyRateProvider extends AbstractRateProvider { + + private static final ProviderContext CONTEXT = ProviderContextBuilder.of(FOLIO_CURRENT.get(), RateType.REALTIME) + .set("providerDescription", FOLIO_CURRENT.getDescription()) + .build(); + private static final HttpClient httpClient= HttpClient.newHttpClient(); + + private static final String FOLIO_DIGIT_FRACTION = "folio.digit.fraction"; + private static final String GET_LATEST_EXCHANGE_RATE_URL = "https://api.currencyapi.com/v3/latest?apikey=%s&base_currency=%s¤cies=%s"; + private static final String CONTENT_TYPE = "Content-Type"; + private static final String APPLICATION_JSON_UTF_8 = "text/application-json;charset=UTF-8"; + private static final String apiKey = System.getenv("API_KEY"); + + public FolioCurrentCurrencyRateProvider() { + super(CONTEXT); + } + + @Override + public ExchangeRate getExchangeRate(ConversionQuery query) { + log.info("getExchangeRate:: Using {} exchange rate provider", FOLIO_CURRENT.get()); + var fromCurrencyCode = query.getBaseCurrency(); + var toCurrencyCode = query.getCurrency(); + + var exchangeRate = getExchangeRateFromApi(fromCurrencyCode.getCurrencyCode(), toCurrencyCode.getCurrencyCode()); + log.info("getExchangeRate:: Exchange rate {} -> {}: {}", fromCurrencyCode, toCurrencyCode, exchangeRate); + var builder = new ExchangeRateBuilder(this.getExchangeContext(FOLIO_DIGIT_FRACTION)); + builder.setBase(fromCurrencyCode); + builder.setTerm(toCurrencyCode); + builder.setFactor(DefaultNumberValue.of(exchangeRate)); + + return builder.build(); + } + + @SneakyThrows + private BigDecimal getExchangeRateFromApi(String fromCurrencyCode, String toCurrencyCode) { + var httpRequest = HttpRequest.newBuilder() + .uri(new URI(String.format(GET_LATEST_EXCHANGE_RATE_URL, apiKey, fromCurrencyCode, toCurrencyCode))) + .headers(CONTENT_TYPE, APPLICATION_JSON_UTF_8) + .GET().build(); + + var httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + log.info("getExchangeRateFromApi:: Status code: {}, body: {}", httpResponse.statusCode() ,httpResponse.body()); + + var value = new JsonObject(httpResponse.body()) + .getJsonObject(CurrencyApiResponseField.DATA.getValue()) + .getJsonObject(toCurrencyCode) + .getString(CurrencyApiResponseField.VALUE.getValue()); + + return new BigDecimal(value); + } +} diff --git a/src/main/java/org/folio/service/exchange/FolioExchangeRateType.java b/src/main/java/org/folio/service/exchange/FolioExchangeRateType.java new file mode 100644 index 000000000..3829aa151 --- /dev/null +++ b/src/main/java/org/folio/service/exchange/FolioExchangeRateType.java @@ -0,0 +1,23 @@ +package org.folio.service.exchange; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import javax.money.convert.ExchangeRateProviderSupplier; + +@Getter +@AllArgsConstructor +public enum FolioExchangeRateType implements ExchangeRateProviderSupplier { + FOLIO_CURRENT("FOLIO_CURRENT", "Custom current exchange rate type for FOLIO"), + FOLIO_HISTORY("FOLIO_HISTORY", "Custom history exchange rate type for FOLIO"); + + @Getter(AccessLevel.NONE) + private final String type; + private final String description; + + @Override + public String get() { + return this.type; + } +} diff --git a/src/main/java/org/folio/service/exchange/FolioHistoryCurrencyRateProvider.java b/src/main/java/org/folio/service/exchange/FolioHistoryCurrencyRateProvider.java new file mode 100644 index 000000000..709ede23b --- /dev/null +++ b/src/main/java/org/folio/service/exchange/FolioHistoryCurrencyRateProvider.java @@ -0,0 +1,34 @@ +package org.folio.service.exchange; + +import lombok.extern.log4j.Log4j2; +import org.javamoney.moneta.spi.AbstractRateProvider; + +import javax.money.convert.ConversionQuery; +import javax.money.convert.ExchangeRate; +import javax.money.convert.ProviderContext; +import javax.money.convert.ProviderContextBuilder; +import javax.money.convert.RateType; + +import static org.folio.service.exchange.FolioExchangeRateType.FOLIO_HISTORY; + +@Log4j2 +public class FolioHistoryCurrencyRateProvider extends AbstractRateProvider { + + private static final ProviderContext CONTEXT = ProviderContextBuilder.of(FOLIO_HISTORY.get(), RateType.HISTORIC) + .set("providerDescription", FOLIO_HISTORY.getDescription()) + .build(); + + public FolioHistoryCurrencyRateProvider() { + super(CONTEXT); + } + + @Override + public ProviderContext getContext() { + return CONTEXT; + } + + @Override + public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) { + return null; + } +} diff --git a/src/main/resources/META-INF/services/javax.money.convert.ExchangeRateProvider b/src/main/resources/META-INF/services/javax.money.convert.ExchangeRateProvider new file mode 100644 index 000000000..65a0d158f --- /dev/null +++ b/src/main/resources/META-INF/services/javax.money.convert.ExchangeRateProvider @@ -0,0 +1,2 @@ +org.folio.service.exchange.FolioCurrentCurrencyRateProvider +org.folio.service.exchange.FolioHistoryCurrencyRateProvider diff --git a/src/main/resources/javamoney.properties b/src/main/resources/javamoney.properties index 7335af2f2..1947c08ac 100644 --- a/src/main/resources/javamoney.properties +++ b/src/main/resources/javamoney.properties @@ -1,17 +1,36 @@ -# ECB Rates +# Standard provider chain +{1}conversion.default-chain=IDENT,FOLIO_CURRENT,ECB,FOLIO_HISTORY + +# Decimal rounding per provider +{1}folio.digit.fraction=6 +{1}ecb.digit.fraction=6 + {1}load.ECBCurrentRateProvider.type=SCHEDULED {1}load.ECBCurrentRateProvider.period=03:00:00 -{1}load.ECBCurrentRateProvider.resource=/java-money/defaults/ECB/eurofxref-daily.xml +{1}load.ECBCurrentRateProvider.resource=org/javamoney/moneta/convert/ecb/defaults/eurofxref-daily.xml {1}load.ECBCurrentRateProvider.urls=https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml {1}load.ECBCurrentRateProvider.startRemote=false -{1}load.ECBHistoric90RateProvider.type=LAZY -{1}load.ECBHistoricRateProvider.type=LAZY -{1}load.ECBHistoric90RateProvider.urls= -{1}load.ECBHistoricRateProvider.urls= -{1}load.IMFHistoricRateProvider.urls= +# Disable ECBHistoric90RateProvider +{1}load.ECBHistoric90RateProvider.type=NEVER +{1}load.ECBHistoric90RateProvider.startRemote=false +{1}load.ECBHistoric90RateProvider.resource=org/javamoney/moneta/convert/ecb/defaults/eurofxref-hist-90d.xml +{1}load.ECBHistoric90RateProvider.urls=https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml + +# Disable ECBHistoricRateProvider +{1}load.ECBHistoricRateProvider.type=NEVER +{1}load.ECBHistoricRateProvider.startRemote=false +{1}load.ECBHistoricRateProvider.resource=org/javamoney/moneta/convert/ecb/defaults/eurofxref-hist.xml +{1}load.ECBHistoricRateProvider.urls=https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml + +# Disable IMFHistoricRateProvider +{1}load.IMFRateProvider.type=NEVER +{1}load.IMFRateProvider.startRemote=false {1}load.IMFRateProvider.urls= -{1}conversion.default-chain=IDENT,ECB +# Disable IMFHistoricRateProvider +{1}load.IMFHistoricRateProvider.type=NEVER +{1}load.IMFHistoricRateProvider.startRemote=false +{1}load.IMFHistoricRateProvider.urls= + -{1}ecb.digit.fraction=6 diff --git a/src/main/resources/kafka.properties b/src/main/resources/kafka.properties index a65ae1354..4bceda530 100644 --- a/src/main/resources/kafka.properties +++ b/src/main/resources/kafka.properties @@ -1,4 +1,3 @@ - order_created_ready_for_post_processing.partitions=${DI_ORDER_CREATED_READY_FOR_POST_PROCESSING_PARTITIONS:1} order_created.partitions=${DI_ORDER_CREATED_PARTITIONS:1} -pending_order_created.partitions=${DI_PENDING_ORDER_CREATED_PARTITIONS:1} \ No newline at end of file +pending_order_created.partitions=${DI_PENDING_ORDER_CREATED_PARTITIONS:1}