Skip to content

Commit 8ab8976

Browse files
committed
fix for investment stream ingestion
1 parent 144d53a commit 8ab8976

File tree

6 files changed

+155
-74
lines changed

6 files changed

+155
-74
lines changed

stream-investment/investment-core/src/main/java/com/backbase/stream/configuration/InvestmentServiceConfiguration.java

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.backbase.investment.api.service.v1.PortfolioApi;
99
import com.backbase.stream.clients.autoconfigure.DbsApiClientsAutoConfiguration;
1010
import com.backbase.stream.investment.saga.InvestmentSaga;
11+
import com.backbase.stream.investment.service.CustomIntegrationApiService;
1112
import com.backbase.stream.investment.service.InvestmentAssetUniverseService;
1213
import com.backbase.stream.investment.service.InvestmentClientService;
1314
import com.backbase.stream.investment.service.InvestmentPortfolioService;
@@ -30,14 +31,34 @@
3031
public class InvestmentServiceConfiguration {
3132

3233
@Bean
33-
public InvestmentSaga investmentSaga(ClientApi clientApi, PortfolioApi portfolioApi,
34+
public InvestmentClientService investmentClientService(ClientApi clientApi) {
35+
return new InvestmentClientService(clientApi);
36+
}
37+
38+
@Bean
39+
public CustomIntegrationApiService customIntegrationApiService(ApiClient apiClient) {
40+
return new CustomIntegrationApiService(apiClient);
41+
}
42+
43+
@Bean
44+
public InvestmentPortfolioService investmentPortfolioService(PortfolioApi portfolioApi,
3445
InvestmentProductsApi investmentProductsApi, FinancialAdviceApi financialAdviceApi,
35-
AssetUniverseApi assetUniverseApi, InvestmentSagaConfigurationProperties properties,
36-
ApiClient apiClient) {
37-
return new InvestmentSaga(
38-
new InvestmentClientService(clientApi),
39-
new InvestmentPortfolioService(investmentProductsApi, portfolioApi, financialAdviceApi),
40-
new InvestmentAssetUniverseService(assetUniverseApi, apiClient));
46+
CustomIntegrationApiService customIntegrationApiService) {
47+
return new InvestmentPortfolioService(investmentProductsApi, portfolioApi, financialAdviceApi,
48+
customIntegrationApiService);
49+
}
50+
51+
@Bean
52+
public InvestmentAssetUniverseService investmentAssetUniverseService(AssetUniverseApi assetUniverseApi,
53+
CustomIntegrationApiService customIntegrationApiService) {
54+
return new InvestmentAssetUniverseService(assetUniverseApi, customIntegrationApiService);
55+
}
56+
57+
@Bean
58+
public InvestmentSaga investmentSaga(InvestmentClientService investmentClientService,
59+
InvestmentPortfolioService investmentPortfolioService,
60+
InvestmentAssetUniverseService investmentAssetUniverseService) {
61+
return new InvestmentSaga(investmentClientService, investmentPortfolioService, investmentAssetUniverseService);
4162
}
4263

4364
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package com.backbase.stream.investment.service;
2+
3+
import com.backbase.investment.api.service.ApiClient;
4+
import com.backbase.investment.api.service.v1.model.Asset;
5+
import com.backbase.investment.api.service.v1.model.OASAssetRequestDataRequest;
6+
import com.backbase.investment.api.service.v1.model.OASModelPortfolioRequestDataRequest;
7+
import com.backbase.investment.api.service.v1.model.OASModelPortfolioResponse;
8+
import java.io.File;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Locale;
12+
import java.util.Map;
13+
import lombok.RequiredArgsConstructor;
14+
import lombok.extern.slf4j.Slf4j;
15+
import org.springframework.core.ParameterizedTypeReference;
16+
import org.springframework.core.io.FileSystemResource;
17+
import org.springframework.http.HttpHeaders;
18+
import org.springframework.http.HttpMethod;
19+
import org.springframework.http.MediaType;
20+
import org.springframework.util.LinkedMultiValueMap;
21+
import org.springframework.util.MultiValueMap;
22+
import org.springframework.web.reactive.function.client.WebClientResponseException;
23+
import reactor.core.publisher.Mono;
24+
25+
@Deprecated(forRemoval = true, since = "8.6.0")
26+
@Slf4j
27+
@RequiredArgsConstructor
28+
public class CustomIntegrationApiService {
29+
30+
private final ApiClient apiClient;
31+
32+
/**
33+
* Creates a new asset by sending a POST request to the asset API.
34+
*
35+
* @param assetRequest the asset request payload
36+
* @return Mono<Asset> representing the created asset
37+
* @throws WebClientResponseException if the API call fails
38+
*/
39+
public Mono<Asset> createAsset(OASAssetRequestDataRequest assetRequest) throws WebClientResponseException {
40+
// create path and map variables
41+
final Map<String, Object> pathParams = new HashMap<String, Object>();
42+
43+
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
44+
final HttpHeaders headerParams = new HttpHeaders();
45+
final MultiValueMap<String, String> cookieParams = new LinkedMultiValueMap<String, String>();
46+
final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
47+
48+
final String[] localVarAccepts = {
49+
"application/json"
50+
};
51+
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
52+
final String[] localVarContentTypes = {
53+
"application/json"
54+
};
55+
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
56+
57+
String[] localVarAuthNames = new String[]{};
58+
59+
ParameterizedTypeReference<Asset> localVarReturnType = new ParameterizedTypeReference<Asset>() {
60+
};
61+
return apiClient.invokeAPI("/service-api/v2/asset/assets/", HttpMethod.POST, pathParams, queryParams,
62+
assetRequest,
63+
headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames,
64+
localVarReturnType)
65+
.bodyToMono(localVarReturnType);
66+
}
67+
68+
public Mono<OASModelPortfolioResponse> createModelPortfolioRequestCreation(
69+
List<String> expand, String fields, String omit, OASModelPortfolioRequestDataRequest data, File image)
70+
throws WebClientResponseException {
71+
// create path and map variables
72+
final Map<String, Object> pathParams = new HashMap<String, Object>();
73+
74+
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
75+
final HttpHeaders headerParams = new HttpHeaders();
76+
final MultiValueMap<String, String> cookieParams = new LinkedMultiValueMap<String, String>();
77+
final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
78+
79+
queryParams.putAll(
80+
apiClient.parameterToMultiValueMap(ApiClient.CollectionFormat.valueOf("multi".toUpperCase(Locale.ROOT)),
81+
"expand", expand));
82+
queryParams.putAll(apiClient.parameterToMultiValueMap(null, "fields", fields));
83+
queryParams.putAll(apiClient.parameterToMultiValueMap(null, "omit", omit));
84+
85+
if (data != null) {
86+
formParams.add("data", data);
87+
}
88+
if (image != null) {
89+
formParams.add("image", new FileSystemResource(image));
90+
}
91+
92+
final String[] localVarAccepts = {
93+
"application/json"
94+
};
95+
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
96+
final String[] localVarContentTypes = {
97+
"application/json"
98+
};
99+
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
100+
101+
String[] localVarAuthNames = new String[]{};
102+
103+
ParameterizedTypeReference<OASModelPortfolioResponse> localVarReturnType = new ParameterizedTypeReference<OASModelPortfolioResponse>() {
104+
};
105+
return apiClient.invokeAPI("/integration-api/v2/advice-engines/model-portfolio/model_portfolios/",
106+
HttpMethod.POST,
107+
pathParams, queryParams, data, headerParams, cookieParams, formParams, localVarAccept,
108+
localVarContentType, localVarAuthNames, localVarReturnType)
109+
.bodyToMono(localVarReturnType);
110+
}
111+
112+
}

stream-investment/investment-core/src/main/java/com/backbase/stream/investment/service/InvestmentAssetUniverseService.java

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,22 @@
11
package com.backbase.stream.investment.service;
22

3-
import com.backbase.investment.api.service.ApiClient;
43
import com.backbase.investment.api.service.v1.AssetUniverseApi;
54
import com.backbase.investment.api.service.v1.model.Asset;
65
import com.backbase.investment.api.service.v1.model.Market;
76
import com.backbase.investment.api.service.v1.model.MarketRequest;
87
import com.backbase.investment.api.service.v1.model.OASAssetRequestDataRequest;
9-
import com.backbase.stream.configuration.InvestmentServiceConfiguration;
108
import java.io.IOException;
11-
import java.util.HashMap;
12-
import java.util.List;
13-
import java.util.Map;
149
import lombok.RequiredArgsConstructor;
1510
import lombok.extern.slf4j.Slf4j;
16-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
17-
import org.springframework.core.ParameterizedTypeReference;
18-
import org.springframework.http.HttpHeaders;
19-
import org.springframework.http.HttpMethod;
20-
import org.springframework.http.MediaType;
21-
import org.springframework.stereotype.Service;
22-
import org.springframework.util.LinkedMultiValueMap;
23-
import org.springframework.util.MultiValueMap;
2411
import org.springframework.web.reactive.function.client.WebClientResponseException;
2512
import reactor.core.publisher.Mono;
2613

2714
@Slf4j
28-
@Service
29-
@ConditionalOnBean(InvestmentServiceConfiguration.class)
3015
@RequiredArgsConstructor
3116
public class InvestmentAssetUniverseService {
3217

3318
private final AssetUniverseApi assetUniverseApi;
34-
private final ApiClient apiClient;
19+
private final CustomIntegrationApiService customIntegrationApiService;
3520

3621
/**
3722
* Gets an existing market by code, or creates it if not found (404). Handles 404 NOT_FOUND from getMarket by
@@ -98,7 +83,7 @@ public Mono<Asset> getOrCreateAsset(final OASAssetRequestDataRequest assetReques
9883
})
9984
// If Mono is empty (asset not found), create the asset
10085
.switchIfEmpty(
101-
createAsset(assetRequest)
86+
customIntegrationApiService.createAsset(assetRequest)
10287
.doOnSuccess(createdAsset -> log.info("Created asset with assetIdentifier: {}", assetIdentifier))
10388
.doOnError(error -> {
10489
if (error instanceof WebClientResponseException) {
@@ -113,40 +98,4 @@ public Mono<Asset> getOrCreateAsset(final OASAssetRequestDataRequest assetReques
11398
);
11499
}
115100

116-
/**
117-
* Creates a new asset by sending a POST request to the asset API.
118-
*
119-
* @param assetRequest the asset request payload
120-
* @return Mono<Asset> representing the created asset
121-
* @throws WebClientResponseException if the API call fails
122-
*/
123-
public Mono<Asset> createAsset(OASAssetRequestDataRequest assetRequest) throws WebClientResponseException {
124-
// create path and map variables
125-
final Map<String, Object> pathParams = new HashMap<String, Object>();
126-
127-
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
128-
final HttpHeaders headerParams = new HttpHeaders();
129-
final MultiValueMap<String, String> cookieParams = new LinkedMultiValueMap<String, String>();
130-
final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
131-
132-
final String[] localVarAccepts = {
133-
"application/json"
134-
};
135-
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
136-
final String[] localVarContentTypes = {
137-
"application/json"
138-
};
139-
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
140-
141-
String[] localVarAuthNames = new String[]{};
142-
143-
ParameterizedTypeReference<Asset> localVarReturnType = new ParameterizedTypeReference<Asset>() {
144-
};
145-
return apiClient.invokeAPI("/service-api/v2/asset/assets/", HttpMethod.POST, pathParams, queryParams,
146-
assetRequest,
147-
headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames,
148-
localVarReturnType)
149-
.bodyToMono(localVarReturnType);
150-
}
151-
152101
}

stream-investment/investment-core/src/main/java/com/backbase/stream/investment/service/InvestmentClientService.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import com.backbase.investment.api.service.v1.model.OASClientUpdateRequest;
77
import com.backbase.investment.api.service.v1.model.PatchedOASClientUpdateRequest;
88
import com.backbase.investment.api.service.v1.model.Status836Enum;
9-
import com.backbase.stream.configuration.InvestmentServiceConfiguration;
109
import com.backbase.stream.investment.ClientUser;
1110
import jakarta.validation.constraints.NotNull;
1211
import java.util.Collections;
@@ -16,8 +15,6 @@
1615
import java.util.UUID;
1716
import lombok.RequiredArgsConstructor;
1817
import lombok.extern.slf4j.Slf4j;
19-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
20-
import org.springframework.stereotype.Service;
2118
import org.springframework.util.CollectionUtils;
2219
import org.springframework.web.reactive.function.client.WebClientResponseException;
2320
import reactor.core.publisher.Mono;
@@ -35,9 +32,7 @@
3532
* </ul>
3633
*/
3734
@Slf4j
38-
@Service
3935
@RequiredArgsConstructor
40-
@ConditionalOnBean(InvestmentServiceConfiguration.class)
4136
public class InvestmentClientService {
4237

4338
private static final String USER_EXTERNAL_ID_KEY = "user_external_id";

stream-investment/investment-core/src/main/java/com/backbase/stream/investment/service/InvestmentPortfolioService.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import com.backbase.investment.api.service.v1.model.PortfolioProductCreateUpdateRequest;
1515
import com.backbase.investment.api.service.v1.model.ProductTypeEnum;
1616
import com.backbase.investment.api.service.v1.model.StatusA3dEnum;
17-
import com.backbase.stream.configuration.InvestmentServiceConfiguration;
1817
import com.backbase.stream.investment.InvestmentArrangement;
1918
import java.time.OffsetDateTime;
2019
import java.util.Arrays;
@@ -26,8 +25,6 @@
2625
import java.util.UUID;
2726
import lombok.RequiredArgsConstructor;
2827
import lombok.extern.slf4j.Slf4j;
29-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
30-
import org.springframework.stereotype.Service;
3128
import org.springframework.util.CollectionUtils;
3229
import org.springframework.web.reactive.function.client.WebClientResponseException;
3330
import reactor.core.publisher.Mono;
@@ -52,9 +49,7 @@
5249
* </ul>
5350
*/
5451
@Slf4j
55-
@Service
5652
@RequiredArgsConstructor
57-
@ConditionalOnBean(InvestmentServiceConfiguration.class)
5853
public class InvestmentPortfolioService {
5954

6055
private static final String DEFAULT_CURRENCY = "EUR";
@@ -63,6 +58,7 @@ public class InvestmentPortfolioService {
6358
private final InvestmentProductsApi productsApi;
6459
private final PortfolioApi portfolioApi;
6560
private final FinancialAdviceApi financialAdviceApi;
61+
private final CustomIntegrationApiService customIntegrationApiService;
6662

6763
/**
6864
* Creates or updates an investment product (portfolio product) for the given arrangement.
@@ -99,11 +95,11 @@ public Mono<PortfolioProduct> upsertInvestmentProducts(InvestmentArrangement inv
9995
if (productType != ProductTypeEnum.SELF_TRADING) {
10096
adviceEngine = "model_portfolio";
10197
if (ProductTypeEnum.ROBO_ADVISOR == productType) {
102-
portfolioModel = new InvestorModelPortfolio(null, "test " + investmentArrangement.getName(), 0.03, 8,
98+
portfolioModel = new InvestorModelPortfolio(null, investmentArrangement.getName(), 1d, 5,
10399
List.of(), null);
104100
}
105101
if (ProductTypeEnum.SAVINGS_PLAN == productType) {
106-
portfolioModel = new InvestorModelPortfolio(null, "test " + investmentArrangement.getName(), 0.0, 8,
102+
portfolioModel = new InvestorModelPortfolio(null, investmentArrangement.getName(), 1d, 5,
107103
List.of(), null);
108104
}
109105
}
@@ -526,9 +522,12 @@ private Mono<OASModelPortfolioResponse> createNewModelPortfolio(InvestorModelPor
526522
modelPortfolio.getName(), modelPortfolio.getRiskLevel());
527523

528524
OASModelPortfolioRequestDataRequest data = new OASModelPortfolioRequestDataRequest();
525+
data.setName(modelPortfolio.getName());
529526
data.cashWeight(modelPortfolio.getCashWeight());
527+
data.allocation(List.of());
528+
data.riskLevel(modelPortfolio.getRiskLevel());
530529
data.description(modelPortfolio.getDescription());
531-
return financialAdviceApi.createModelPortfolio(null, null, null,
530+
return customIntegrationApiService.createModelPortfolioRequestCreation(null, null, null,
532531
data, null)
533532
.doOnSuccess(created -> log.info(
534533
"Successfully created model portfolio: uuid={}, name={}, riskLevel={}",

stream-investment/investment-core/src/test/java/com/backbase/stream/investment/service/InvestmentAssetUniverseServiceTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,22 @@
2222
import java.io.IOException;
2323
import java.nio.charset.StandardCharsets;
2424

25+
/**
26+
* This is a custom implementations to avoid issues with Reactive and multipart requests
27+
*/
2528
class InvestmentAssetUniverseServiceTest {
2629

2730
InvestmentAssetUniverseService service;
2831
AssetUniverseApi assetUniverseApi;
2932
ApiClient apiClient;
33+
CustomIntegrationApiService customIntegrationApiService;
3034

3135
@BeforeEach
3236
void setUp() {
3337
assetUniverseApi = Mockito.mock(AssetUniverseApi.class);
3438
apiClient = Mockito.mock(ApiClient.class);
35-
service = new InvestmentAssetUniverseService(assetUniverseApi, apiClient);
39+
customIntegrationApiService = Mockito.spy(new CustomIntegrationApiService(apiClient));
40+
service = new InvestmentAssetUniverseService(assetUniverseApi, customIntegrationApiService);
3641
}
3742

3843
@Test

0 commit comments

Comments
 (0)