Skip to content
Merged
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
8 changes: 6 additions & 2 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,12 @@
"version": "1.2"
},
{
"id": "settings",
"version": "1.2"
"id": "locale",
"version": "1.0"
},
{
"id": "tenant-addresses",
"version": "1.0"
}
],
"optional": [
Expand Down
7 changes: 4 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@
<wiremock.version>2.27.2</wiremock.version>
<localstack.version>1.20.5</localstack.version>
<marc4j.version>2.9.1</marc4j.version>
<testcontainers.version>1.17.6</testcontainers.version>
<testcontainers.version>2.0.3</testcontainers.version>
<testcontainers.extensions.version>1.21.4</testcontainers.extensions.version>
<aws.sdk.version>2.40.2</aws.sdk.version>
<folio-s3-client.version>3.0.0-SNAPSHOT</folio-s3-client.version>
<hamcrest-all.version>1.3</hamcrest-all.version>
Expand Down Expand Up @@ -262,14 +263,14 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
<version>${testcontainers.extensions.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>${testcontainers.version}</version>
<version>${testcontainers.extensions.version}</version>
<scope>test</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import java.util.UUID;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.folio.dew.client.SettingsClient;
import org.folio.dew.client.TenantAddressesClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

Expand All @@ -17,9 +17,11 @@
public class ConfigurationService {

private static final Logger logger = LogManager.getLogger();
private static final String ADDRESSES = "addresses";
private static final String ID = "id";
private static final String ADDRESS = "address";

private final SettingsClient settingsClient;
private final ObjectMapper objectMapper;
private final TenantAddressesClient tenantAddressesClient;

@Cacheable(cacheNames = "addressConfiguration")
public String getAddressConfig(UUID shipToConfigId) {
Expand All @@ -28,18 +30,30 @@ public String getAddressConfig(UUID shipToConfigId) {
return "";
}
try {
var settingEntry = settingsClient.getSettingById(shipToConfigId.toString());
JsonNode addressesResponse = tenantAddressesClient.getTenantAddresses();

if (settingEntry == null || !settingEntry.containsKey("value")) {
logger.warn("getAddressConfig:: Address on the config with id '{}' is not found", shipToConfigId);
if (addressesResponse == null || !addressesResponse.has(ADDRESSES)) {
logger.warn("getAddressConfig:: No addresses found in tenant-addresses response");
return "";
}

var value = settingEntry.get("value");
JsonNode valueJsonObject = objectMapper.valueToTree(value);
return valueJsonObject.has("address") ? valueJsonObject.get("address").asText() : "";
JsonNode addressesList = addressesResponse.get(ADDRESSES);
if (!addressesList.isArray() || addressesList.isEmpty()) {
logger.warn("getAddressConfig:: Addresses list is empty");
return "";
}

for (JsonNode addressEntry : addressesList) {
String addressId = addressEntry.path(ID).asText(null);
if (StringUtils.equals(shipToConfigId.toString(), addressId)) {
logger.info("getAddressConfig:: Found address with id '{}'", shipToConfigId);
return addressEntry.path(ADDRESS).asText("");
}
}

return "";
} catch (Exception e) {
logger.warn("getAddressConfig:: Cannot find config by id: '{}'", shipToConfigId, e);
logger.warn("getAddressConfig:: Cannot find address by id: '{}'", shipToConfigId, e);
return "";
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package org.folio.dew.batch.circulationlog;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.folio.dew.client.LocaleClient;
import org.folio.dew.client.ServicePointClient;
import org.folio.dew.client.SettingsClient;
import org.folio.dew.domain.dto.CirculationLogExportFormat;
import org.folio.dew.domain.dto.LogRecord;
import org.folio.dew.domain.dto.LogRecordItemsInner;
Expand All @@ -19,7 +18,6 @@

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.stream.Collectors;
Expand All @@ -31,8 +29,7 @@
public class CirculationLogItemProcessor implements ItemProcessor<LogRecord, CirculationLogExportFormat> {

private final ServicePointClient servicePointClient;
private final SettingsClient settingsClient;
private final ObjectMapper objectMapper;
private final LocaleClient localeClient;

private Map<String, String> servicePointMap;
private SimpleDateFormat format;
Expand Down Expand Up @@ -75,32 +72,16 @@ private void initTenantSpecificDateFormat() {
format = dateFormat;
}

@SneakyThrows
@SuppressWarnings("unchecked")
private String fetchTimezone() {
try {
final Map<String, Object> tenantLocaleSettings =
settingsClient.getSettings("scope==stripes-core.prefs.manage and key==tenantLocaleSettings");

var resultInfo = (Map<String, Object>) tenantLocaleSettings.get("resultInfo");
var totalRecords = (Integer) resultInfo.get("totalRecords");

if (totalRecords > 0) {
var items = (List<Map<String, Object>>) tenantLocaleSettings.get("items");
var settingsEntry = items.get(0);
var value = settingsEntry.get("value");

if (value instanceof String valueStr) {
return valueStr;
} else {
var jsonObject = objectMapper.valueToTree(value);
if (jsonObject.has("timezone")) {
return jsonObject.get("timezone").asText();
}
}
JsonNode localeSettings = localeClient.getLocale();

if (localeSettings != null && localeSettings.has("timezone")) {
return localeSettings.get("timezone").asText("UTC");
}
log.warn("Timezone not found in locale settings, using default UTC");
} catch (Exception e) {
log.warn("Failed to fetch timezone from mod-settings: {}", e.getMessage());
log.warn("Failed to fetch timezone from locale endpoint: {}", e.getMessage());
}

return "UTC";
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/folio/dew/client/LocaleClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.folio.dew.client;

import com.fasterxml.jackson.databind.JsonNode;
import org.folio.dew.config.feign.FeignClientConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;


@FeignClient(name = "locale", configuration = FeignClientConfiguration.class)
public interface LocaleClient {

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
JsonNode getLocale();
}
29 changes: 0 additions & 29 deletions src/main/java/org/folio/dew/client/SettingsClient.java

This file was deleted.

15 changes: 15 additions & 0 deletions src/main/java/org/folio/dew/client/TenantAddressesClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.folio.dew.client;

import com.fasterxml.jackson.databind.JsonNode;
import org.folio.dew.config.feign.FeignClientConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;


@FeignClient(name = "tenant-addresses", configuration = FeignClientConfiguration.class)
public interface TenantAddressesClient {

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
JsonNode getTenantAddresses();
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.time.LocalDate;
import java.util.UUID;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.folio.de.entity.JobCommand;
import org.folio.dew.config.kafka.KafkaService;
import org.folio.dew.domain.dto.JobParameterNames;
Expand All @@ -36,7 +37,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;

class AuthorityControlConsortiumTest extends BaseBatchTest {

Expand Down
2 changes: 1 addition & 1 deletion src/test/java/org/folio/dew/AuthorityControlTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.UUID;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FileUtils;
import org.folio.de.entity.JobCommand;
import org.folio.dew.config.kafka.KafkaService;
import org.folio.dew.domain.dto.ExportType;
Expand All @@ -41,7 +42,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;

@Log4j2
class AuthorityControlTest extends BaseBatchTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,87 @@
package org.folio.dew.batch.acquisitions.services;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import java.util.UUID;
import java.util.stream.Stream;
import org.folio.dew.BaseBatchTest;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;

class ConfigurationServiceTest extends BaseBatchTest {
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

@Autowired
import org.folio.dew.client.TenantAddressesClient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ConfigurationServiceTest {

private static final ObjectMapper MAPPER = new ObjectMapper();
private static final UUID CONFIG_ID = UUID.fromString("1947e709-8d60-42e2-8dde-7566ae446d24");
private static final String EXPECTED_ADDRESS = "Address 123";

@Mock
private TenantAddressesClient tenantAddressesClient;

@InjectMocks
private ConfigurationService configurationService;

@BeforeAll
static void beforeAll() {
setUpTenant(NON_CONSORTIUM_TENANT);
@Test
void getAddressConfig_nullId_returnsEmpty() {
assertThat(configurationService.getAddressConfig(null)).isEmpty();
}

@Test
void getAddressConfig_matchingAddress_returnsAddress() {
when(tenantAddressesClient.getTenantAddresses())
.thenReturn(createResponse(CONFIG_ID.toString(), EXPECTED_ADDRESS));

assertThat(configurationService.getAddressConfig(CONFIG_ID)).isEqualTo(EXPECTED_ADDRESS);
}

@Test
void getAddressConfig_noMatchingId_returnsEmpty() {
when(tenantAddressesClient.getTenantAddresses())
.thenReturn(createResponse("other-id", "Other Address"));

assertThat(configurationService.getAddressConfig(CONFIG_ID)).isEmpty();
}

static Stream<Arguments> testGetAddressConfigArgs() {
return Stream.of(
Arguments.of(null, ""), // No config id
Arguments.of("1947e709-8d60-42e2-8dde-7566ae446d24", "Address 123"), // Config with address
Arguments.of("8ea92aa2-7b11-4f0e-9ed2-ab8fe281f37f", ""), // Config without address
Arguments.of("116a38c2-cac3-4f08-816b-afebfebe453d", ""), // Config without a body
Arguments.of("c5cefe49-e4d4-433e-b286-24ffd935b043", "") // No config
);
@Test
void getAddressConfig_nullResponse_returnsEmpty() {
when(tenantAddressesClient.getTenantAddresses()).thenReturn(null);

assertThat(configurationService.getAddressConfig(CONFIG_ID)).isEmpty();
}

@Test
void getAddressConfig_emptyAddressArray_returnsEmpty() {
ObjectNode response = MAPPER.createObjectNode();
response.putArray("addresses");
when(tenantAddressesClient.getTenantAddresses()).thenReturn(response);

assertThat(configurationService.getAddressConfig(CONFIG_ID)).isEmpty();
}

@ParameterizedTest
@MethodSource("testGetAddressConfigArgs")
void testGetAddressConfig(String addressConfigId, String expectedAddress) {
var configId = addressConfigId != null ? UUID.fromString(addressConfigId) : null;
assertEquals(expectedAddress, configurationService.getAddressConfig(configId));
@Test
void getAddressConfig_clientThrowsException_returnsEmpty() {
when(tenantAddressesClient.getTenantAddresses())
.thenThrow(new RuntimeException("Connection error"));

assertThat(configurationService.getAddressConfig(CONFIG_ID)).isEmpty();
}

// -- Helper --

private static ObjectNode createResponse(String id, String address) {
ObjectNode response = MAPPER.createObjectNode();
ArrayNode addresses = response.putArray("addresses");
ObjectNode entry = addresses.addObject();
entry.put("id", id);
entry.put("address", address);
return response;
}
}
}
Loading
Loading