-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MODFQMMGR-202: Include system exchange rate in Lists app (#218)
* MODFQMMGR-202: Include system exchange rate in Lists app * Update POL definition in 1.2.0
- Loading branch information
1 parent
ada6952
commit adab2f7
Showing
16 changed files
with
925 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
162 changes: 162 additions & 0 deletions
162
src/main/java/org/folio/fqm/repository/DataRefreshRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
package org.folio.fqm.repository; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.jayway.jsonpath.DocumentContext; | ||
import com.jayway.jsonpath.JsonPath; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.log4j.Log4j2; | ||
import org.folio.fqm.client.SimpleHttpClient; | ||
import org.jooq.DSLContext; | ||
import org.jooq.Field; | ||
import org.jooq.Record2; | ||
import org.jooq.impl.DSL; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static org.jooq.impl.DSL.field; | ||
import static org.jooq.impl.DSL.table; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
@Log4j2 | ||
public class DataRefreshRepository { | ||
|
||
public static final Field<String> CURRENCY_FIELD = field("currency", String.class); | ||
public static final Field<Double> EXCHANGE_RATE_FIELD = field("exchange_rate", Double.class); | ||
|
||
private static final String REFRESH_MATERIALIZED_VIEW_SQL = "REFRESH MATERIALIZED VIEW CONCURRENTLY "; | ||
private static final String GET_EXCHANGE_RATE_PATH = "finance/exchange-rate"; | ||
private static final String GET_LOCALE_SETTINGS_PATH = "configurations/entries"; | ||
private static final Map<String, String> GET_LOCALE_SETTINGS_PARAMS = Map.of( | ||
"query", "(module==ORG and configName==localeSettings)" | ||
); | ||
|
||
private static final List<String> MATERIALIZED_VIEW_NAMES = List.of( | ||
"drv_circulation_loan_status", | ||
"drv_inventory_item_status", | ||
"drv_pol_payment_status", | ||
"drv_pol_receipt_status", | ||
"drv_inventory_statistical_code_full", | ||
"drv_languages" | ||
); | ||
|
||
static final List<String> SYSTEM_SUPPORTED_CURRENCIES = List.of( | ||
"USD", | ||
"JPY", | ||
"BGN", | ||
"CZK", | ||
"DKK", | ||
"GBP", | ||
"HUF", | ||
"PLN", | ||
"RON", | ||
"SEK", | ||
"CHF", | ||
"ISK", | ||
"NOK", | ||
"HRK", | ||
"RUB", | ||
"TRY", | ||
"AUD", | ||
"BRL", | ||
"CAD", | ||
"CNY", | ||
"HKD", | ||
"IDR", | ||
"ILS", | ||
"INR", | ||
"KRW", | ||
"MXN", | ||
"MYR", | ||
"NZD", | ||
"PHP", | ||
"SGD", | ||
"THB", | ||
"ZAR" | ||
); | ||
|
||
private final DSLContext jooqContext; | ||
|
||
private final SimpleHttpClient simpleHttpClient; | ||
|
||
public void refreshMaterializedViews(String tenantId) { | ||
for (String matViewName : MATERIALIZED_VIEW_NAMES) { | ||
String fullName = tenantId + "_mod_fqm_manager." + matViewName; | ||
log.info("Refreshing materialized view {}", fullName); | ||
jooqContext.execute(REFRESH_MATERIALIZED_VIEW_SQL + fullName); | ||
} | ||
} | ||
|
||
public void refreshExchangeRates(String tenantId) { | ||
log.info("Refreshing exchange rates"); | ||
String fullTableName = tenantId + "_mod_fqm_manager.currency_exchange_rates"; | ||
String systemCurrency = getSystemCurrencyCode(); | ||
if (!SYSTEM_SUPPORTED_CURRENCIES.contains(systemCurrency)) { | ||
log.info("System currency does not support automatic exchange rate calculation"); | ||
return; | ||
} | ||
|
||
List<Record2<String, Double>> exchangeRates = new ArrayList<>(); | ||
for (String currency : SYSTEM_SUPPORTED_CURRENCIES) { | ||
Double exchangeRate = getExchangeRate(currency, systemCurrency); | ||
if (!Double.isNaN(exchangeRate)) { | ||
Record2<String, Double> currencyExchangeRate = jooqContext | ||
.newRecord(CURRENCY_FIELD, EXCHANGE_RATE_FIELD) | ||
.value1(currency) | ||
.value2(exchangeRate); | ||
exchangeRates.add(currencyExchangeRate); | ||
} | ||
} | ||
|
||
jooqContext.insertInto(table(fullTableName), CURRENCY_FIELD, EXCHANGE_RATE_FIELD) | ||
.valuesOfRecords(exchangeRates) | ||
.onConflict(CURRENCY_FIELD) | ||
.doUpdate() | ||
.set(EXCHANGE_RATE_FIELD, DSL.field("EXCLUDED." + EXCHANGE_RATE_FIELD.getName(), Double.class)) | ||
.execute(); | ||
} | ||
|
||
private String getSystemCurrencyCode() { | ||
log.info("Getting system currency"); | ||
try { | ||
String localeSettingsResponse = simpleHttpClient.get(GET_LOCALE_SETTINGS_PATH, GET_LOCALE_SETTINGS_PARAMS); | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
JsonNode localeSettingsNode = objectMapper.readTree(localeSettingsResponse); | ||
String valueString = localeSettingsNode | ||
.path("configs") | ||
.get(0) | ||
.path("value") | ||
.asText(); | ||
JsonNode valueNode = objectMapper.readTree(valueString); | ||
return valueNode.path("currency").asText(); | ||
} catch (Exception e) { | ||
log.info("No system currency defined, defaulting to USD"); | ||
return "USD"; | ||
} | ||
} | ||
|
||
private Double getExchangeRate(String fromCurrency, String toCurrency) { | ||
log.info("Getting currency exchange rate from {} to {}", fromCurrency, toCurrency); | ||
Map<String, String> exchangeRateParams = Map.of( | ||
"from", fromCurrency, | ||
"to", toCurrency | ||
); | ||
try { | ||
String exchangeRateResponse = simpleHttpClient.get(GET_EXCHANGE_RATE_PATH, exchangeRateParams); | ||
DocumentContext exchangeRateInfo = JsonPath.parse(exchangeRateResponse); | ||
var exchangeRate = exchangeRateInfo.read("exchangeRate"); | ||
if (exchangeRate instanceof BigDecimal bd) { | ||
return bd.doubleValue(); | ||
} | ||
return (Double) exchangeRate; | ||
} catch (Exception e) { | ||
log.info("Failed to get exchange rate from {} to {}", fromCurrency, toCurrency); | ||
return Double.NaN; | ||
} | ||
} | ||
} |
34 changes: 0 additions & 34 deletions
34
src/main/java/org/folio/fqm/repository/MaterializedViewRefreshRepository.java
This file was deleted.
Oops, something went wrong.
10 changes: 5 additions & 5 deletions
10
...ce/MaterializedViewRefreshController.java → ...o/fqm/resource/DataRefreshController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,21 @@ | ||
package org.folio.fqm.resource; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.folio.fqm.service.MaterializedViewRefreshService; | ||
import org.folio.fqm.service.DataRefreshService; | ||
import org.folio.spring.FolioExecutionContext; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
public class MaterializedViewRefreshController implements MaterializedViewsApi { | ||
public class DataRefreshController implements MaterializedViewsApi { | ||
private final FolioExecutionContext executionContext; | ||
private final MaterializedViewRefreshService materializedViewRefreshService; | ||
private final DataRefreshService dataRefreshService; | ||
|
||
@Override | ||
public ResponseEntity<Void> refreshMaterializedViews() { | ||
materializedViewRefreshService.refreshMaterializedViews(executionContext.getTenantId()); | ||
public ResponseEntity<Void> refreshData() { | ||
dataRefreshService.refreshData(executionContext.getTenantId()); | ||
return new ResponseEntity<>(HttpStatus.NO_CONTENT); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/org/folio/fqm/service/DataRefreshService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.folio.fqm.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.folio.fqm.repository.DataRefreshRepository; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class DataRefreshService { | ||
private final DataRefreshRepository dataRefreshRepository; | ||
|
||
public void refreshData(String tenantId) { | ||
dataRefreshRepository.refreshMaterializedViews(tenantId); | ||
dataRefreshRepository.refreshExchangeRates(tenantId); | ||
} | ||
} |
15 changes: 0 additions & 15 deletions
15
src/main/java/org/folio/fqm/service/MaterializedViewRefreshService.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/main/resources/db/changelog/changes/v1.1.1/changelog-v1.1.1.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.1" encoding="UTF-8" standalone="no"?> | ||
<databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog" | ||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd"> | ||
|
||
<changeSet id="MODFQMMGR-202" author="[email protected]" runOnChange="true"> | ||
<sqlFile path="sql/create-table-currency-exchange-rates.sql" relativeToChangelogFile="true"/> | ||
</changeSet> | ||
<include file="update-drv-purchase-order-line-details-definition.xml" relativeToChangelogFile="true"/> | ||
|
||
</databaseChangeLog> |
4 changes: 4 additions & 0 deletions
4
src/main/resources/db/changelog/changes/v1.1.1/sql/create-table-currency-exchange-rates.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
CREATE TABLE IF NOT EXISTS currency_exchange_rates( | ||
currency VARCHAR(8) PRIMARY KEY, | ||
exchange_rate FLOAT | ||
); |
Oops, something went wrong.