|
|
|
@ -18,7 +18,7 @@ import { |
|
|
|
ActivityResponse |
|
|
|
} from '@ghostfolio/common/interfaces'; |
|
|
|
import { permissions } from '@ghostfolio/common/permissions'; |
|
|
|
import type { DateRange, RequestWithUser } from '@ghostfolio/common/types'; |
|
|
|
import type { RequestWithUser } from '@ghostfolio/common/types'; |
|
|
|
|
|
|
|
import { |
|
|
|
Body, |
|
|
|
@ -29,7 +29,6 @@ import { |
|
|
|
HttpException, |
|
|
|
Inject, |
|
|
|
Param, |
|
|
|
ParseIntPipe, |
|
|
|
Post, |
|
|
|
Put, |
|
|
|
Query, |
|
|
|
@ -38,11 +37,13 @@ import { |
|
|
|
} from '@nestjs/common'; |
|
|
|
import { REQUEST } from '@nestjs/core'; |
|
|
|
import { AuthGuard } from '@nestjs/passport'; |
|
|
|
import { Order, Prisma, Type as ActivityType } from '@prisma/client'; |
|
|
|
import { Order } from '@prisma/client'; |
|
|
|
import { parseISO } from 'date-fns'; |
|
|
|
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; |
|
|
|
|
|
|
|
import { ActivitiesService } from './activities.service'; |
|
|
|
import { DeleteActivitiesDto } from './delete-activities.dto'; |
|
|
|
import { GetActivitiesDto } from './get-activities.dto'; |
|
|
|
|
|
|
|
@Controller('activities') |
|
|
|
export class ActivitiesController { |
|
|
|
@ -60,36 +61,30 @@ export class ActivitiesController { |
|
|
|
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) |
|
|
|
@UseInterceptors(TransformDataSourceInRequestInterceptor) |
|
|
|
public async deleteActivities( |
|
|
|
@Query('accounts') filterByAccounts?: string, |
|
|
|
@Query('activityTypes') filterByTypes?: string, |
|
|
|
@Query('assetClasses') filterByAssetClasses?: string, |
|
|
|
@Query('dataSource') filterByDataSource?: string, |
|
|
|
@Query('range') dateRange?: DateRange, |
|
|
|
@Query('symbol') filterBySymbol?: string, |
|
|
|
@Query('tags') filterByTags?: string |
|
|
|
@Query() query: DeleteActivitiesDto |
|
|
|
): Promise<number> { |
|
|
|
let endDate: Date; |
|
|
|
let startDate: Date; |
|
|
|
|
|
|
|
if (dateRange) { |
|
|
|
({ endDate, startDate } = getIntervalFromDateRange({ dateRange })); |
|
|
|
if (query.range) { |
|
|
|
({ endDate, startDate } = getIntervalFromDateRange({ |
|
|
|
dateRange: query.range |
|
|
|
})); |
|
|
|
} |
|
|
|
|
|
|
|
const filters = this.apiService.buildFiltersFromQueryParams({ |
|
|
|
filterByAccounts, |
|
|
|
filterByAssetClasses, |
|
|
|
filterByDataSource, |
|
|
|
filterBySymbol, |
|
|
|
filterByTags |
|
|
|
filterByAccounts: query.accounts, |
|
|
|
filterByAssetClasses: query.assetClasses, |
|
|
|
filterByDataSource: query.dataSource, |
|
|
|
filterBySymbol: query.symbol, |
|
|
|
filterByTags: query.tags |
|
|
|
}); |
|
|
|
|
|
|
|
const types = this.parseActivityTypes(filterByTypes); |
|
|
|
|
|
|
|
return this.activitiesService.deleteActivities({ |
|
|
|
endDate, |
|
|
|
filters, |
|
|
|
startDate, |
|
|
|
types, |
|
|
|
types: query.activityTypes, |
|
|
|
userId: this.request.user.id |
|
|
|
}); |
|
|
|
} |
|
|
|
@ -122,51 +117,41 @@ export class ActivitiesController { |
|
|
|
@UseInterceptors(TransformDataSourceInResponseInterceptor) |
|
|
|
public async getAllActivities( |
|
|
|
@Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, |
|
|
|
@Query('accounts') filterByAccounts?: string, |
|
|
|
@Query('activityTypes') filterByTypes?: string, |
|
|
|
@Query('assetClasses') filterByAssetClasses?: string, |
|
|
|
@Query('dataSource') filterByDataSource?: string, |
|
|
|
@Query('range') dateRange?: DateRange, |
|
|
|
@Query('skip', new ParseIntPipe({ optional: true })) skip?: number, |
|
|
|
@Query('sortColumn') sortColumn?: string, |
|
|
|
@Query('sortDirection') sortDirection?: Prisma.SortOrder, |
|
|
|
@Query('symbol') filterBySymbol?: string, |
|
|
|
@Query('tags') filterByTags?: string, |
|
|
|
@Query('take', new ParseIntPipe({ optional: true })) take?: number |
|
|
|
@Query() query: GetActivitiesDto |
|
|
|
): Promise<ActivitiesResponse> { |
|
|
|
let endDate: Date; |
|
|
|
let startDate: Date; |
|
|
|
|
|
|
|
if (dateRange) { |
|
|
|
({ endDate, startDate } = getIntervalFromDateRange({ dateRange })); |
|
|
|
if (query.range) { |
|
|
|
({ endDate, startDate } = getIntervalFromDateRange({ |
|
|
|
dateRange: query.range |
|
|
|
})); |
|
|
|
} |
|
|
|
|
|
|
|
const filters = this.apiService.buildFiltersFromQueryParams({ |
|
|
|
filterByAccounts, |
|
|
|
filterByAssetClasses, |
|
|
|
filterByDataSource, |
|
|
|
filterBySymbol, |
|
|
|
filterByTags |
|
|
|
filterByAccounts: query.accounts, |
|
|
|
filterByAssetClasses: query.assetClasses, |
|
|
|
filterByDataSource: query.dataSource, |
|
|
|
filterBySymbol: query.symbol, |
|
|
|
filterByTags: query.tags |
|
|
|
}); |
|
|
|
|
|
|
|
const impersonationUserId = |
|
|
|
await this.impersonationService.validateImpersonationId(impersonationId); |
|
|
|
|
|
|
|
const types = this.parseActivityTypes(filterByTypes); |
|
|
|
|
|
|
|
const userCurrency = this.request.user.settings.settings.baseCurrency; |
|
|
|
|
|
|
|
const { activities, count } = await this.activitiesService.getActivities({ |
|
|
|
endDate, |
|
|
|
filters, |
|
|
|
skip, |
|
|
|
sortColumn, |
|
|
|
sortDirection, |
|
|
|
startDate, |
|
|
|
take, |
|
|
|
types, |
|
|
|
userCurrency, |
|
|
|
includeDrafts: true, |
|
|
|
skip: query.skip, |
|
|
|
sortColumn: query.sortColumn, |
|
|
|
sortDirection: query.sortDirection, |
|
|
|
take: query.take, |
|
|
|
types: query.activityTypes, |
|
|
|
userId: impersonationUserId || this.request.user.id, |
|
|
|
withExcludedAccountsAndActivities: true |
|
|
|
}); |
|
|
|
@ -360,28 +345,4 @@ export class ActivitiesController { |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private parseActivityTypes(filterByTypes?: string): ActivityType[] { |
|
|
|
if (!filterByTypes) { |
|
|
|
return []; |
|
|
|
} |
|
|
|
|
|
|
|
const types = filterByTypes.split(','); |
|
|
|
|
|
|
|
const invalidTypes = types.filter((type) => { |
|
|
|
return !Object.values(ActivityType).includes(type as ActivityType); |
|
|
|
}); |
|
|
|
|
|
|
|
if (invalidTypes.length > 0) { |
|
|
|
throw new HttpException( |
|
|
|
{ |
|
|
|
error: getReasonPhrase(StatusCodes.BAD_REQUEST), |
|
|
|
message: [`Invalid activity type: ${invalidTypes.join(', ')}`] |
|
|
|
}, |
|
|
|
StatusCodes.BAD_REQUEST |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
return types as ActivityType[]; |
|
|
|
} |
|
|
|
} |
|
|
|
|