250 lines
9.7 KiB
Java
250 lines
9.7 KiB
Java
package zw.qantra.tm.domain.services;
|
|
|
|
import lombok.Getter;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.cache.annotation.CacheEvict;
|
|
import org.springframework.cache.annotation.Cacheable;
|
|
import org.springframework.data.domain.Pageable;
|
|
import org.springframework.data.jpa.domain.Specification;
|
|
import org.springframework.http.HttpHeaders;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
import zw.qantra.tm.domain.dtos.SBZProductDto;
|
|
import zw.qantra.tm.domain.models.Provider;
|
|
import zw.qantra.tm.domain.repositories.ProviderRepository;
|
|
import zw.qantra.tm.exceptions.ApiException;
|
|
import zw.qantra.tm.rest.RestService;
|
|
import zw.qantra.tm.utils.Utils;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
@Slf4j
|
|
public class ProviderService {
|
|
@Getter
|
|
private final ProviderRepository providerRepository;
|
|
private final RestService restService;
|
|
private final HotRechargeTokenService hotRechargeTokenService;
|
|
|
|
@Value("${hot.api.url:https://ssl.hot.co.zw/api/v3}")
|
|
private String hotApiUrl;
|
|
|
|
@Value("${sbz.aggregator.url}")
|
|
private String aggregatorUrl;
|
|
|
|
public SBZProductDto getProviderProduct(UUID providerId, UUID productId) {
|
|
return getProviderProducts(providerId.toString()).stream()
|
|
.filter(product -> product.getUid().equals(productId))
|
|
.findFirst()
|
|
.orElse(null);
|
|
}
|
|
|
|
@Deprecated
|
|
public List<SBZProductDto> getProviderProducts(UUID providerId) {
|
|
String token = restService.getMerchantToken();
|
|
|
|
HttpHeaders headers = new HttpHeaders();
|
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
|
headers.setBearerAuth(token);
|
|
|
|
LinkedHashMap response;
|
|
try {
|
|
response = this.restService.getAs(
|
|
aggregatorUrl + "/merchant/aggregation/products?size=20&clientUid=" + providerId.toString(),
|
|
headers,
|
|
LinkedHashMap.class
|
|
);
|
|
} catch (Exception e) {
|
|
log.error("Error fetching products for provider " + providerId, e);
|
|
return Collections.emptyList();
|
|
}
|
|
|
|
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
|
List<LinkedHashMap> content = (List<LinkedHashMap>) body.get("content");
|
|
|
|
List<SBZProductDto> products = new ArrayList<>();
|
|
for (LinkedHashMap product : content) {
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
SBZProductDto productDto = mapper.convertValue(product, SBZProductDto.class);
|
|
products.add(productDto);
|
|
}
|
|
|
|
return products;
|
|
}
|
|
|
|
// todo: figure out caching for different providers
|
|
// @Cacheable(value = "providerProducts", key = "#providerUid")
|
|
public List<SBZProductDto> getProviderProducts(String providerUid) {
|
|
try {
|
|
Provider provider = providerRepository.findById(UUID.fromString(providerUid)).orElse(null);
|
|
if (provider == null) {
|
|
return Collections.emptyList();
|
|
}
|
|
Map<String, String> meta = Utils.fromJson(provider.getMeta(), Map.class);
|
|
String providerId = meta.get("hotProductId");
|
|
|
|
String stockUrl = hotApiUrl + "/query/stock/" + providerId;
|
|
HttpHeaders headers = new HttpHeaders();
|
|
String token = hotRechargeTokenService.getToken();
|
|
headers.setBearerAuth(token);
|
|
|
|
LinkedHashMap<String, Object> response;
|
|
try {
|
|
response = restService.getAs(stockUrl, headers, LinkedHashMap.class);
|
|
} catch (Exception e) {
|
|
log.error("Error fetching products for provider " + providerId);
|
|
return Collections.emptyList();
|
|
}
|
|
|
|
List stock = (List) response.get("stock");
|
|
List<SBZProductDto> products = new ArrayList<>();
|
|
for (Object item : stock) {
|
|
LinkedHashMap<String, Object> stockItem = (LinkedHashMap<String, Object>) item;
|
|
int stockProviderId = (int) stockItem.get("productId"); // providerId is referred to as productId in the stock response
|
|
if (String.valueOf(stockProviderId).equals(providerId)) {
|
|
log.info("Found matching provider in stock: " + stockItem);
|
|
|
|
SBZProductDto sbzProductDto = new SBZProductDto();
|
|
sbzProductDto.setName((String) stockItem.get("name"));
|
|
sbzProductDto.setDescription((String) stockItem.get("description"));
|
|
sbzProductDto.setDisplayName((String) stockItem.get("name"));
|
|
sbzProductDto.setDefaultAmount(new BigDecimal(stockItem.get("amount").toString()));
|
|
sbzProductDto.setRequiresAmount(true); // always true for now
|
|
sbzProductDto.setUid(UUID.fromString(Utils.getUid()));
|
|
sbzProductDto.setExternalId((String) stockItem.get("productCode"));
|
|
products.add(sbzProductDto);
|
|
}
|
|
}
|
|
|
|
return products;
|
|
} catch (IllegalArgumentException e) {
|
|
log.error("Error fetching products: {}", providerUid);
|
|
return Collections.emptyList();
|
|
}
|
|
}
|
|
|
|
public String getProviderId(String billClientId) {
|
|
Provider provider = getProviderRepository()
|
|
.findByClientId(billClientId);
|
|
if(provider == null){
|
|
throw new ApiException("Provider not found for billClientId: " + billClientId);
|
|
}
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, String> meta = Utils.fromJson(provider.getMeta(), Map.class);
|
|
return meta.get("hotProductId");
|
|
}
|
|
|
|
public String getExternalId(String providerId, String productName) {
|
|
try {
|
|
List<SBZProductDto> products = getProviderProducts(providerId);
|
|
|
|
return products.stream()
|
|
.filter(product -> product.getName().equals(productName))
|
|
.map(SBZProductDto::getExternalId)
|
|
.findFirst()
|
|
.orElse(null);
|
|
} catch (Exception e) {
|
|
log.error("Failed to fetch external Id: " + productName, e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public Object getProviderByClientId(String clientId) {
|
|
return providerRepository.findByClientId(clientId);
|
|
}
|
|
|
|
public Object findAll(Specification<Provider> specification, Pageable pageable) {
|
|
return getProviderRepository().findAll(specification, pageable);
|
|
}
|
|
|
|
public Object getProviders(List<Provider> existingProviders) {
|
|
String token = restService.getMerchantToken();
|
|
|
|
HttpHeaders headers = new HttpHeaders();
|
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
|
headers.setBearerAuth(token);
|
|
|
|
List<String> existingProviderIds = existingProviders.stream()
|
|
.map(Provider::getClientId)
|
|
.collect(Collectors.toList());
|
|
String existingProviderIdsString = String.join(",", existingProviderIds);
|
|
|
|
LinkedHashMap response = this.restService.getAs(
|
|
aggregatorUrl + "/merchant/aggregation/providers?supportedCurrencies=USD&clientIdIn=" + existingProviderIdsString,
|
|
headers,
|
|
LinkedHashMap.class
|
|
);
|
|
|
|
LinkedHashMap body = (LinkedHashMap) response.get("body");
|
|
List<LinkedHashMap> content = (List<LinkedHashMap>) body.get("content");
|
|
|
|
for (LinkedHashMap provider : content) {
|
|
String clientId = (String) provider.get("clientId");
|
|
if (existingProviderIds.contains(clientId)) {
|
|
// Update existing provider
|
|
Provider existingProvider = existingProviders.stream()
|
|
.filter(p -> p.getClientId().equals(clientId))
|
|
.findFirst()
|
|
.orElse(null);
|
|
if (existingProvider != null) {
|
|
provider.put("name", existingProvider.getDescription());
|
|
provider.put("description", existingProvider.getDescription());
|
|
provider.put("image", existingProvider.getImage());
|
|
provider.put("label", existingProvider.getLabel());
|
|
provider.put("category", existingProvider.getCategory());
|
|
provider.put("accountFieldName", existingProvider.getAccountFieldName());
|
|
}
|
|
}
|
|
}
|
|
|
|
return content;
|
|
}
|
|
|
|
public Optional<Provider> getProvider(UUID id) {
|
|
return providerRepository.findById(id);
|
|
}
|
|
|
|
public Provider createProvider(Provider provider) {
|
|
return providerRepository.save(provider);
|
|
}
|
|
|
|
public Provider updateProvider(UUID id, Provider provider) {
|
|
if (providerRepository.existsById(id)) {
|
|
provider.setId(id);
|
|
return providerRepository.save(provider);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public boolean deleteProvider(UUID id) {
|
|
if (providerRepository.existsById(id)) {
|
|
providerRepository.deleteById(id);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Evict ALL providerProducts cache entries
|
|
@CacheEvict(value = "providerProducts", allEntries = true)
|
|
public void evictProviderProductsCache() {
|
|
// empty - annotation handles the eviction
|
|
}
|
|
|
|
// Or evict a SINGLE entry by key
|
|
@CacheEvict(value = "providerProducts", key = "#providerUid")
|
|
public void evictProviderProductCache(String providerUid) {
|
|
// only evicts cache for this specific providerUid
|
|
}
|
|
|
|
} |