Skip to content

Commit b91f0b1

Browse files
author
pawana_backbase
committed
Generating Intraday Prices for the Assets
1 parent 4291272 commit b91f0b1

File tree

11 files changed

+449
-20
lines changed

11 files changed

+449
-20
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.backbase.stream.investment.service.InvestmentAssetPriceService;
1818
import com.backbase.stream.investment.service.InvestmentAssetUniverseService;
1919
import com.backbase.stream.investment.service.InvestmentClientService;
20+
import com.backbase.stream.investment.service.InvestmentIntradayAssetPriceService;
2021
import com.backbase.stream.investment.service.InvestmentModelPortfolioService;
2122
import com.backbase.stream.investment.service.InvestmentPortfolioAllocationService;
2223
import com.backbase.stream.investment.service.InvestmentPortfolioService;
@@ -73,6 +74,11 @@ public InvestmentAssetPriceService investmentAssetPriceService(AssetUniverseApi
7374
return new InvestmentAssetPriceService(assetUniverseApi);
7475
}
7576

77+
@Bean
78+
public InvestmentIntradayAssetPriceService investmentIntradayAssetPriceService(AssetUniverseApi assetUniverseApi) {
79+
return new InvestmentIntradayAssetPriceService(assetUniverseApi);
80+
}
81+
7682
@Bean
7783
public InvestmentPortfolioAllocationService investmentPortfolioAllocationService(AllocationsApi allocationsApi,
7884
AssetUniverseApi assetUniverseApi, InvestmentApi investmentApi,
@@ -96,9 +102,10 @@ public InvestmentSaga investmentSaga(InvestmentClientService investmentClientSer
96102
public InvestmentAssetUniversSaga investmentStaticDataSaga(
97103
InvestmentAssetUniverseService investmentAssetUniverseService,
98104
InvestmentAssetPriceService investmentAssetPriceService,
105+
InvestmentIntradayAssetPriceService investmentIntradayAssetPriceService,
99106
InvestmentIngestionConfigurationProperties coreConfigurationProperties) {
100107
return new InvestmentAssetUniversSaga(investmentAssetUniverseService, investmentAssetPriceService,
101-
coreConfigurationProperties);
108+
investmentIntradayAssetPriceService, coreConfigurationProperties);
102109
}
103110

104111
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.backbase.stream.investment;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import java.util.UUID;
5+
6+
public record AssetLatestPrice(@JsonProperty("uuid") UUID uuid,
7+
@JsonProperty("latest_price") LatestPrice latestPrice) {}

stream-investment/investment-core/src/main/java/com/backbase/stream/investment/InvestmentAssetData.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class InvestmentAssetData {
2727
private List<Asset> assets;
2828
private List<AssetPrice> assetPrices;
2929
private List<GroupResult> priceAsyncTasks;
30+
private List<GroupResult> intradayPriceAsyncTasks;
3031

3132
public Map<String, AssetPrice> getPriceByAsset() {
3233
return Objects.requireNonNullElse(assetPrices, List.<AssetPrice>of()).stream()

stream-investment/investment-core/src/main/java/com/backbase/stream/investment/InvestmentAssetsTask.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,8 @@ public InvestmentAssetsTask setPriceTasks(List<GroupResult> tasks) {
5151
return this;
5252
}
5353

54+
public InvestmentAssetsTask setIntradayPriceTasks(List<GroupResult> tasks) {
55+
data.setIntradayPriceAsyncTasks(tasks);
56+
return this;
57+
}
5458
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.backbase.stream.investment;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import java.time.OffsetDateTime;
5+
6+
public record LatestPrice(
7+
@JsonProperty("amount") Double amount,
8+
@JsonProperty("datetime") OffsetDateTime datetime,
9+
@JsonProperty("open_price") Double openPrice,
10+
@JsonProperty("high_price") Double highPrice,
11+
@JsonProperty("low_price") Double lowPrice,
12+
@JsonProperty("previous_close_price") Double previousClosePrice
13+
) {
14+
15+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.backbase.stream.investment;
2+
3+
import java.net.URI;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import lombok.Builder;
7+
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
10+
@EqualsAndHashCode
11+
@Data
12+
@Builder
13+
public class PaginatedExpandedAssetList {
14+
15+
public static final String JSON_PROPERTY_COUNT = "count";
16+
private Integer count;
17+
18+
public static final String JSON_PROPERTY_NEXT = "next";
19+
private URI next;
20+
21+
public static final String JSON_PROPERTY_PREVIOUS = "previous";
22+
private URI previous;
23+
24+
public static final String JSON_PROPERTY_RESULTS = "results";
25+
private List<AssetLatestPrice> results = new ArrayList<>();
26+
27+
}

stream-investment/investment-core/src/main/java/com/backbase/stream/investment/saga/InvestmentAssetUniversSaga.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.backbase.stream.investment.service.InvestmentAssetPriceService;
1111
import com.backbase.stream.investment.service.InvestmentAssetUniverseService;
1212
import com.backbase.stream.investment.service.InvestmentClientService;
13+
import com.backbase.stream.investment.service.InvestmentIntradayAssetPriceService;
1314
import com.backbase.stream.investment.service.InvestmentPortfolioService;
1415
import com.backbase.stream.worker.StreamTaskExecutor;
1516
import com.backbase.stream.worker.model.StreamTask;
@@ -59,32 +60,34 @@ public class InvestmentAssetUniversSaga implements StreamTaskExecutor<Investment
5960

6061
private final InvestmentAssetUniverseService assetUniverseService;
6162
private final InvestmentAssetPriceService investmentAssetPriceService;
63+
private final InvestmentIntradayAssetPriceService investmentIntradayAssetPriceService;
6264
private final InvestmentIngestionConfigurationProperties coreConfigurationProperties;
6365

6466
@Override
6567
public Mono<InvestmentAssetsTask> executeTask(InvestmentAssetsTask streamTask) {
6668
if (!coreConfigurationProperties.isAssetUniversEnabled()) {
67-
log.warn("Skip investment asset univers saga execution: taskId={}, taskName={}",
69+
log.warn("Skip investment asset universe saga execution: taskId={}, taskName={}",
6870
streamTask.getId(), streamTask.getName());
6971
return Mono.just(streamTask);
7072
}
71-
log.info("Starting investment saga execution: taskId={}, taskName={}",
73+
log.info("Starting investment asset universe saga execution: taskId={}, taskName={}",
7274
streamTask.getId(), streamTask.getName());
73-
return createMarkets(streamTask)
74-
.flatMap(this::createMarketSpecialDays)
75-
.flatMap(this::createAssetCategoryTypes)
76-
.flatMap(this::createAssetCategories)
75+
return upsertMarkets(streamTask)
76+
.flatMap(this::upsertMarketSpecialDays)
77+
.flatMap(this::upsertAssetCategoryTypes)
78+
.flatMap(this::upsertAssetCategories)
7779
.flatMap(this::createAssets)
7880
.flatMap(this::upsertPrices)
81+
.flatMap(this::upsertIntradayPrices)
7982
.doOnSuccess(completedTask -> log.info(
80-
"Successfully completed investment saga: taskId={}, taskName={}, state={}",
83+
"Successfully completed investment asset universe saga: taskId={}, taskName={}, state={}",
8184
completedTask.getId(), completedTask.getName(), completedTask.getState()))
8285
.doOnError(throwable -> {
83-
log.error("Failed to execute investment saga: taskId={}, taskName={}",
86+
log.error("Failed to execute investment asset universe saga: taskId={}, taskName={}",
8487
streamTask.getId(), streamTask.getName(), throwable);
8588
streamTask.error(INVESTMENT, OP_UPSERT, RESULT_FAILED,
8689
streamTask.getName(), streamTask.getId(),
87-
"Investment saga failed: " + throwable.getMessage());
90+
"Investment asset universe saga failed: " + throwable.getMessage());
8891
streamTask.setState(State.FAILED);
8992
})
9093
.onErrorResume(throwable -> Mono.just(streamTask));
@@ -96,6 +99,11 @@ private Mono<InvestmentAssetsTask> upsertPrices(InvestmentAssetsTask investmentT
9699
.map(investmentTask::setPriceTasks);
97100
}
98101

102+
private Mono<InvestmentAssetsTask> upsertIntradayPrices(InvestmentAssetsTask investmentTask) {
103+
return investmentIntradayAssetPriceService.ingestIntradayPrices()
104+
.map(investmentTask::setIntradayPriceTasks);
105+
}
106+
99107
/**
100108
* Rollback is not implemented for investment saga.
101109
*
@@ -112,7 +120,7 @@ public Mono<InvestmentAssetsTask> rollBack(InvestmentAssetsTask streamTask) {
112120
return Mono.empty();
113121
}
114122

115-
public Mono<InvestmentAssetsTask> createMarkets(InvestmentAssetsTask investmentTask) {
123+
public Mono<InvestmentAssetsTask> upsertMarkets(InvestmentAssetsTask investmentTask) {
116124
InvestmentAssetData investmentData = investmentTask.getData();
117125
int marketCount = investmentData.getMarkets() != null ? investmentData.getMarkets().size() : 0;
118126
log.info("Starting investment market creation: taskId={}, marketCount={}",
@@ -161,15 +169,15 @@ public Mono<InvestmentAssetsTask> createMarkets(InvestmentAssetsTask investmentT
161169
}
162170

163171
/**
164-
* Creates or upserts market special days for the investment task.
172+
* Upserts market special days for the investment task.
165173
*
166174
* <p>This method processes each market special day in the task data by invoking
167175
* the asset universe service. It updates the task state and logs progress for observability.
168176
*
169177
* @param investmentTask the investment task containing market special day data
170178
* @return Mono emitting the updated investment task with market special days set
171179
*/
172-
public Mono<InvestmentAssetsTask> createMarketSpecialDays(InvestmentAssetsTask investmentTask) {
180+
public Mono<InvestmentAssetsTask> upsertMarketSpecialDays(InvestmentAssetsTask investmentTask) {
173181
InvestmentAssetData investmentData = investmentTask.getData();
174182
int marketSpecialDayCount =
175183
investmentData.getMarketSpecialDays() != null ? investmentData.getMarketSpecialDays().size() : 0;
@@ -219,15 +227,15 @@ public Mono<InvestmentAssetsTask> createMarketSpecialDays(InvestmentAssetsTask i
219227
}
220228

221229
/**
222-
* Creates or upserts asset categories for the investment task.
230+
* Upserts asset categories for the investment task.
223231
*
224232
* <p>This method processes each asset category in the task data by invoking
225233
* the asset universe service. It updates the task state and logs progress for observability.
226234
*
227235
* @param investmentTask the investment task containing asset category data
228236
* @return Mono emitting the updated investment task with asset categories set
229237
*/
230-
public Mono<InvestmentAssetsTask> createAssetCategories(InvestmentAssetsTask investmentTask) {
238+
public Mono<InvestmentAssetsTask> upsertAssetCategories(InvestmentAssetsTask investmentTask) {
231239
InvestmentAssetData investmentData = investmentTask.getData();
232240
int categoryCount =
233241
investmentData.getAssetCategories() != null ? investmentData.getAssetCategories().size() : 0;
@@ -274,7 +282,7 @@ public Mono<InvestmentAssetsTask> createAssetCategories(InvestmentAssetsTask inv
274282
});
275283
}
276284

277-
public Mono<InvestmentAssetsTask> createAssetCategoryTypes(InvestmentAssetsTask investmentTask) {
285+
public Mono<InvestmentAssetsTask> upsertAssetCategoryTypes(InvestmentAssetsTask investmentTask) {
278286
InvestmentAssetData investmentData = investmentTask.getData();
279287
int typeCount =
280288
investmentData.getAssetCategoryTypes() != null ? investmentData.getAssetCategoryTypes().size() : 0;

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

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,17 @@ public Mono<Market> getOrCreateMarket(MarketRequest marketRequest) {
5959
.flatMap(existingMarket -> {
6060
log.info("Market already exists: {}", existingMarket.getCode());
6161
log.debug("Market already exists: {}", existingMarket);
62-
return Mono.just(existingMarket);
62+
return assetUniverseApi.updateMarket(existingMarket.getCode(), marketRequest)
63+
.doOnSuccess(updatedMarket -> log.info("Updated market: {}", updatedMarket))
64+
.doOnError(error -> {
65+
if (error instanceof WebClientResponseException w) {
66+
log.error("Error updating market: {} : HTTP {} -> {}", marketRequest.getCode(),
67+
w.getStatusCode(), w.getResponseBodyAsString());
68+
} else {
69+
log.error("Error updating market: {} : {}", marketRequest.getCode(),
70+
error.getMessage(), error);
71+
}
72+
});
6373
})
6474
// If Mono is empty (market not found), create the market
6575
.switchIfEmpty(assetUniverseApi.createMarket(marketRequest)
@@ -141,7 +151,20 @@ public Mono<MarketSpecialDay> getOrCreateMarketSpecialDay(MarketSpecialDayReques
141151
.findFirst();
142152
if (matchingSpecialDay.isPresent()) {
143153
log.info("Market special day already exists for day: {}", marketSpecialDayRequest);
144-
return Mono.just(matchingSpecialDay.get());
154+
return assetUniverseApi.updateMarketSpecialDay(matchingSpecialDay.get().getUuid().toString(),
155+
marketSpecialDayRequest)
156+
.doOnSuccess(updatedMarketSpecialDay ->
157+
log.info("Updated market special day: {}", updatedMarketSpecialDay))
158+
.doOnError(error -> {
159+
if (error instanceof WebClientResponseException w) {
160+
log.error("Error updating market special day : {} : HTTP {} -> {}",
161+
marketSpecialDayRequest,
162+
w.getStatusCode(), w.getResponseBodyAsString());
163+
} else {
164+
log.error("Error updating market special day {} : {}", marketSpecialDayRequest,
165+
error.getMessage(), error);
166+
}
167+
});
145168
} else {
146169
log.debug("No market special day exists for day: {}", marketSpecialDayRequest);
147170
return Mono.empty();
@@ -212,7 +235,18 @@ public Mono<AssetCategory> createAssetCategory(AssetCategoryRequest assetCategor
212235
.findFirst();
213236
if (matchingCategory.isPresent()) {
214237
log.info("Asset category already exists for code: {}", assetCategoryRequest.getCode());
215-
return Mono.just(matchingCategory.get());
238+
return assetUniverseApi.updateAssetCategory(matchingCategory.get().getUuid().toString(), assetCategoryRequest)
239+
.doOnSuccess(updatedCategory -> log.info("Updated asset category: {}", updatedCategory))
240+
.doOnError(error -> {
241+
if (error instanceof WebClientResponseException w) {
242+
log.error("Error updating asset category: {} : HTTP {} -> {}", assetCategoryRequest.getCode(),
243+
w.getStatusCode(), w.getResponseBodyAsString());
244+
} else {
245+
log.error("Error updating asset category: {} : {}", assetCategoryRequest.getCode(),
246+
error.getMessage(), error);
247+
}
248+
})
249+
.onErrorResume(e -> Mono.empty());
216250
} else {
217251
log.debug("No asset category exists for code: {}", assetCategoryRequest.getCode());
218252
return Mono.empty();
@@ -232,6 +266,7 @@ public Mono<AssetCategory> createAssetCategory(AssetCategoryRequest assetCategor
232266
error.getMessage(), error);
233267
}
234268
})
269+
.onErrorResume(e -> Mono.empty())
235270
);
236271
}
237272

@@ -259,7 +294,18 @@ public Mono<AssetCategoryType> createAssetCategoryType(AssetCategoryTypeRequest
259294
.findFirst();
260295
if (matchingType.isPresent()) {
261296
log.info("Asset category type already exists for code: {}", assetCategoryTypeRequest.getCode());
262-
return Mono.just(matchingType.get());
297+
return assetUniverseApi.updateAssetCategoryType(matchingType.get().getUuid().toString(), assetCategoryTypeRequest)
298+
.doOnSuccess(updatedType -> log.info("Updated asset category type: {}", updatedType))
299+
.doOnError(error -> {
300+
if (error instanceof WebClientResponseException w) {
301+
log.error("Error updating asset category type: {} : HTTP {} -> {}",
302+
assetCategoryTypeRequest.getCode(), w.getStatusCode(), w.getResponseBodyAsString());
303+
} else {
304+
log.error("Error updating asset category type: {} : {}",
305+
assetCategoryTypeRequest.getCode(), error.getMessage(), error);
306+
}
307+
})
308+
.onErrorResume(e -> Mono.empty());
263309
} else {
264310
log.debug("No asset category type exists for code: {}", assetCategoryTypeRequest.getCode());
265311
return Mono.empty();

0 commit comments

Comments
 (0)