Feature/extend filters of order endpoint (#3743)
* Extend filters of order endpoint * Update changelog --------- Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
This commit is contained in:
parent
a5211f6a29
commit
383a02519a
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Extended the filters of the activities endpoint by `dataSource` and `symbol`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Optimized the asynchronous operations using `Promise.all()` in the info service
|
- Optimized the asynchronous operations using `Promise.all()` in the info service
|
||||||
|
@ -94,15 +94,18 @@ export class OrderController {
|
|||||||
@Get()
|
@Get()
|
||||||
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
|
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
|
||||||
@UseInterceptors(RedactValuesInResponseInterceptor)
|
@UseInterceptors(RedactValuesInResponseInterceptor)
|
||||||
|
@UseInterceptors(TransformDataSourceInRequestInterceptor)
|
||||||
@UseInterceptors(TransformDataSourceInResponseInterceptor)
|
@UseInterceptors(TransformDataSourceInResponseInterceptor)
|
||||||
public async getAllOrders(
|
public async getAllOrders(
|
||||||
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId,
|
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId,
|
||||||
@Query('accounts') filterByAccounts?: string,
|
@Query('accounts') filterByAccounts?: string,
|
||||||
@Query('assetClasses') filterByAssetClasses?: string,
|
@Query('assetClasses') filterByAssetClasses?: string,
|
||||||
|
@Query('dataSource') filterByDataSource?: string,
|
||||||
@Query('range') dateRange?: DateRange,
|
@Query('range') dateRange?: DateRange,
|
||||||
@Query('skip') skip?: number,
|
@Query('skip') skip?: number,
|
||||||
@Query('sortColumn') sortColumn?: string,
|
@Query('sortColumn') sortColumn?: string,
|
||||||
@Query('sortDirection') sortDirection?: Prisma.SortOrder,
|
@Query('sortDirection') sortDirection?: Prisma.SortOrder,
|
||||||
|
@Query('symbol') filterBySymbol?: string,
|
||||||
@Query('tags') filterByTags?: string,
|
@Query('tags') filterByTags?: string,
|
||||||
@Query('take') take?: number
|
@Query('take') take?: number
|
||||||
): Promise<Activities> {
|
): Promise<Activities> {
|
||||||
@ -116,6 +119,8 @@ export class OrderController {
|
|||||||
const filters = this.apiService.buildFiltersFromQueryParams({
|
const filters = this.apiService.buildFiltersFromQueryParams({
|
||||||
filterByAccounts,
|
filterByAccounts,
|
||||||
filterByAssetClasses,
|
filterByAssetClasses,
|
||||||
|
filterByDataSource,
|
||||||
|
filterBySymbol,
|
||||||
filterByTags
|
filterByTags
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -350,6 +350,14 @@ export class OrderService {
|
|||||||
return type;
|
return type;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filterByDataSource = filters?.find(({ type }) => {
|
||||||
|
return type === 'DATA_SOURCE';
|
||||||
|
})?.id;
|
||||||
|
|
||||||
|
const filterBySymbol = filters?.find(({ type }) => {
|
||||||
|
return type === 'SYMBOL';
|
||||||
|
})?.id;
|
||||||
|
|
||||||
const searchQuery = filters?.find(({ type }) => {
|
const searchQuery = filters?.find(({ type }) => {
|
||||||
return type === 'SEARCH_QUERY';
|
return type === 'SEARCH_QUERY';
|
||||||
})?.id;
|
})?.id;
|
||||||
@ -395,6 +403,29 @@ export class OrderService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filterByDataSource && filterBySymbol) {
|
||||||
|
if (where.SymbolProfile) {
|
||||||
|
where.SymbolProfile = {
|
||||||
|
AND: [
|
||||||
|
where.SymbolProfile,
|
||||||
|
{
|
||||||
|
AND: [
|
||||||
|
{ dataSource: <DataSource>filterByDataSource },
|
||||||
|
{ symbol: filterBySymbol }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
where.SymbolProfile = {
|
||||||
|
AND: [
|
||||||
|
{ dataSource: <DataSource>filterByDataSource },
|
||||||
|
{ symbol: filterBySymbol }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (searchQuery) {
|
if (searchQuery) {
|
||||||
const searchQueryWhereInput: Prisma.SymbolProfileWhereInput[] = [
|
const searchQueryWhereInput: Prisma.SymbolProfileWhereInput[] = [
|
||||||
{ id: { mode: 'insensitive', startsWith: searchQuery } },
|
{ id: { mode: 'insensitive', startsWith: searchQuery } },
|
||||||
|
@ -39,12 +39,12 @@ export class TransformDataSourceInRequestInterceptor<T>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.body.dataSource && !DataSource[request.body.dataSource]) {
|
for (const type of ['body', 'params', 'query']) {
|
||||||
request.body.dataSource = decodeDataSource(request.body.dataSource);
|
const dataSourceValue = request[type]?.dataSource;
|
||||||
}
|
|
||||||
|
|
||||||
if (request.params.dataSource && !DataSource[request.params.dataSource]) {
|
if (dataSourceValue && !DataSource[dataSourceValue]) {
|
||||||
request.params.dataSource = decodeDataSource(request.params.dataSource);
|
request[type].dataSource = decodeDataSource(dataSourceValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,22 +10,28 @@ export class ApiService {
|
|||||||
filterByAccounts,
|
filterByAccounts,
|
||||||
filterByAssetClasses,
|
filterByAssetClasses,
|
||||||
filterByAssetSubClasses,
|
filterByAssetSubClasses,
|
||||||
|
filterByDataSource,
|
||||||
filterByHoldingType,
|
filterByHoldingType,
|
||||||
filterBySearchQuery,
|
filterBySearchQuery,
|
||||||
|
filterBySymbol,
|
||||||
filterByTags
|
filterByTags
|
||||||
}: {
|
}: {
|
||||||
filterByAccounts?: string;
|
filterByAccounts?: string;
|
||||||
filterByAssetClasses?: string;
|
filterByAssetClasses?: string;
|
||||||
filterByAssetSubClasses?: string;
|
filterByAssetSubClasses?: string;
|
||||||
|
filterByDataSource?: string;
|
||||||
filterByHoldingType?: string;
|
filterByHoldingType?: string;
|
||||||
filterBySearchQuery?: string;
|
filterBySearchQuery?: string;
|
||||||
|
filterBySymbol?: string;
|
||||||
filterByTags?: string;
|
filterByTags?: string;
|
||||||
}): Filter[] {
|
}): Filter[] {
|
||||||
const accountIds = filterByAccounts?.split(',') ?? [];
|
const accountIds = filterByAccounts?.split(',') ?? [];
|
||||||
const assetClasses = filterByAssetClasses?.split(',') ?? [];
|
const assetClasses = filterByAssetClasses?.split(',') ?? [];
|
||||||
const assetSubClasses = filterByAssetSubClasses?.split(',') ?? [];
|
const assetSubClasses = filterByAssetSubClasses?.split(',') ?? [];
|
||||||
|
const dataSource = filterByDataSource;
|
||||||
const holdingType = filterByHoldingType;
|
const holdingType = filterByHoldingType;
|
||||||
const searchQuery = filterBySearchQuery?.toLowerCase();
|
const searchQuery = filterBySearchQuery?.toLowerCase();
|
||||||
|
const symbol = filterBySymbol;
|
||||||
const tagIds = filterByTags?.split(',') ?? [];
|
const tagIds = filterByTags?.split(',') ?? [];
|
||||||
|
|
||||||
const filters = [
|
const filters = [
|
||||||
@ -55,6 +61,13 @@ export class ApiService {
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (dataSource) {
|
||||||
|
filters.push({
|
||||||
|
id: dataSource,
|
||||||
|
type: 'DATA_SOURCE'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (holdingType) {
|
if (holdingType) {
|
||||||
filters.push({
|
filters.push({
|
||||||
id: holdingType,
|
id: holdingType,
|
||||||
@ -69,6 +82,13 @@ export class ApiService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (symbol) {
|
||||||
|
filters.push({
|
||||||
|
id: symbol,
|
||||||
|
type: 'SYMBOL'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
public activityForm: FormGroup;
|
public activityForm: FormGroup;
|
||||||
public accounts: Account[];
|
public accounts: Account[];
|
||||||
public activities: Activity[];
|
|
||||||
public assetClass: string;
|
public assetClass: string;
|
||||||
public assetSubClass: string;
|
public assetSubClass: string;
|
||||||
public averagePrice: number;
|
public averagePrice: number;
|
||||||
@ -174,6 +173,22 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
|||||||
.subscribe();
|
.subscribe();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.dataService
|
||||||
|
.fetchActivities({
|
||||||
|
filters: [
|
||||||
|
{ id: this.data.dataSource, type: 'DATA_SOURCE' },
|
||||||
|
{ id: this.data.symbol, type: 'SYMBOL' }
|
||||||
|
],
|
||||||
|
sortColumn: this.sortColumn,
|
||||||
|
sortDirection: this.sortDirection
|
||||||
|
})
|
||||||
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
|
.subscribe(({ activities }) => {
|
||||||
|
this.dataSource = new MatTableDataSource(activities);
|
||||||
|
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchHoldingDetail({
|
.fetchHoldingDetail({
|
||||||
dataSource: this.data.dataSource,
|
dataSource: this.data.dataSource,
|
||||||
@ -198,7 +213,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
|||||||
netPerformancePercent,
|
netPerformancePercent,
|
||||||
netPerformancePercentWithCurrencyEffect,
|
netPerformancePercentWithCurrencyEffect,
|
||||||
netPerformanceWithCurrencyEffect,
|
netPerformanceWithCurrencyEffect,
|
||||||
orders,
|
|
||||||
quantity,
|
quantity,
|
||||||
SymbolProfile,
|
SymbolProfile,
|
||||||
tags,
|
tags,
|
||||||
@ -206,12 +220,10 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
|||||||
value
|
value
|
||||||
}) => {
|
}) => {
|
||||||
this.accounts = accounts;
|
this.accounts = accounts;
|
||||||
this.activities = orders;
|
|
||||||
this.averagePrice = averagePrice;
|
this.averagePrice = averagePrice;
|
||||||
this.benchmarkDataItems = [];
|
this.benchmarkDataItems = [];
|
||||||
this.countries = {};
|
this.countries = {};
|
||||||
this.dataProviderInfo = dataProviderInfo;
|
this.dataProviderInfo = dataProviderInfo;
|
||||||
this.dataSource = new MatTableDataSource(orders.reverse());
|
|
||||||
this.dividendInBaseCurrency = dividendInBaseCurrency;
|
this.dividendInBaseCurrency = dividendInBaseCurrency;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -311,7 +311,7 @@
|
|||||||
animationDuration="0"
|
animationDuration="0"
|
||||||
class="mb-5"
|
class="mb-5"
|
||||||
[mat-stretch-tabs]="false"
|
[mat-stretch-tabs]="false"
|
||||||
[ngClass]="{ 'd-none': !activities?.length }"
|
[ngClass]="{ 'd-none': !dataSource?.data.length }"
|
||||||
>
|
>
|
||||||
<mat-tab>
|
<mat-tab>
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
@ -422,7 +422,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@if (
|
@if (
|
||||||
activities?.length > 0 && data.hasPermissionToReportDataGlitch === true
|
dataSource?.data.length > 0 &&
|
||||||
|
data.hasPermissionToReportDataGlitch === true
|
||||||
) {
|
) {
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
@ -72,14 +72,24 @@ export class DataService {
|
|||||||
ACCOUNT: filtersByAccount,
|
ACCOUNT: filtersByAccount,
|
||||||
ASSET_CLASS: filtersByAssetClass,
|
ASSET_CLASS: filtersByAssetClass,
|
||||||
ASSET_SUB_CLASS: filtersByAssetSubClass,
|
ASSET_SUB_CLASS: filtersByAssetSubClass,
|
||||||
|
DATA_SOURCE: [filterByDataSource],
|
||||||
HOLDING_TYPE: filtersByHoldingType,
|
HOLDING_TYPE: filtersByHoldingType,
|
||||||
PRESET_ID: filtersByPresetId,
|
PRESET_ID: filtersByPresetId,
|
||||||
SEARCH_QUERY: filtersBySearchQuery,
|
SEARCH_QUERY: filtersBySearchQuery,
|
||||||
|
SYMBOL: [filterBySymbol],
|
||||||
TAG: filtersByTag
|
TAG: filtersByTag
|
||||||
} = groupBy(filters, (filter) => {
|
} = groupBy(filters, (filter) => {
|
||||||
return filter.type;
|
return filter.type;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (filterByDataSource) {
|
||||||
|
params = params.append('dataSource', filterByDataSource.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterBySymbol) {
|
||||||
|
params = params.append('symbol', filterBySymbol.id);
|
||||||
|
}
|
||||||
|
|
||||||
if (filtersByAccount) {
|
if (filtersByAccount) {
|
||||||
params = params.append(
|
params = params.append(
|
||||||
'accounts',
|
'accounts',
|
||||||
|
@ -5,6 +5,7 @@ export interface Filter {
|
|||||||
| 'ACCOUNT'
|
| 'ACCOUNT'
|
||||||
| 'ASSET_CLASS'
|
| 'ASSET_CLASS'
|
||||||
| 'ASSET_SUB_CLASS'
|
| 'ASSET_SUB_CLASS'
|
||||||
|
| 'DATA_SOURCE'
|
||||||
| 'HOLDING_TYPE'
|
| 'HOLDING_TYPE'
|
||||||
| 'PRESET_ID'
|
| 'PRESET_ID'
|
||||||
| 'SEARCH_QUERY'
|
| 'SEARCH_QUERY'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user