Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MODORDERS-1232]. SPIKE - Investigate whether javamoney can be used with alternate exchange rate sources #1087

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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&currencies=%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");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An API_KEY must be supplied for it to work (create a trial account here: https://currencyapi.com)


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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.folio.service.exchange.FolioCurrentCurrencyRateProvider
org.folio.service.exchange.FolioHistoryCurrencyRateProvider
37 changes: 28 additions & 9 deletions src/main/resources/javamoney.properties
Original file line number Diff line number Diff line change
@@ -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
3 changes: 1 addition & 2 deletions src/main/resources/kafka.properties
Original file line number Diff line number Diff line change
@@ -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}
pending_order_created.partitions=${DI_PENDING_ORDER_CREATED_PARTITIONS:1}
Loading