|
|
@ -12,7 +12,10 @@ import { DataProviderService } from '@ghostfolio/api/services/data-provider/data |
|
|
import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; |
|
|
import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; |
|
|
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; |
|
|
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; |
|
|
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; |
|
|
import { getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; |
|
|
import { DATA_GATHERING_QUEUE_PRIORITY_HIGH } from '@ghostfolio/common/config'; |
|
|
import { |
|
|
|
|
|
DATA_GATHERING_QUEUE_PRIORITY_HIGH, |
|
|
|
|
|
NON_INVESTMENT_ACTIVITY_TYPES |
|
|
|
|
|
} from '@ghostfolio/common/config'; |
|
|
import { CreateOrderDto, UpdateOrderDto } from '@ghostfolio/common/dtos'; |
|
|
import { CreateOrderDto, UpdateOrderDto } from '@ghostfolio/common/dtos'; |
|
|
import { SubscriptionType } from '@ghostfolio/common/enums'; |
|
|
import { SubscriptionType } from '@ghostfolio/common/enums'; |
|
|
import { |
|
|
import { |
|
|
@ -241,36 +244,12 @@ export class ActivitiesController { |
|
|
userSubscription |
|
|
userSubscription |
|
|
}: ImpersonationContext |
|
|
}: ImpersonationContext |
|
|
): Promise<CreateActivityResponse> { |
|
|
): Promise<CreateActivityResponse> { |
|
|
// Evaluate the more restrictive subscription of the authenticated user
|
|
|
await this.validateActivity({ |
|
|
// and the owner of the activity
|
|
|
authenticatedUserSubscription, |
|
|
const subscription = |
|
|
|
|
|
userSubscription?.type === SubscriptionType.Basic |
|
|
|
|
|
? userSubscription |
|
|
|
|
|
: authenticatedUserSubscription; |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
await this.dataProviderService.validateActivities({ |
|
|
|
|
|
subscription, |
|
|
|
|
|
userId, |
|
|
userId, |
|
|
activitiesDto: [ |
|
|
userSubscription, |
|
|
{ |
|
|
activityDto: data |
|
|
currency: data.currency, |
|
|
|
|
|
dataSource: data.dataSource, |
|
|
|
|
|
symbol: data.symbol, |
|
|
|
|
|
type: data.type |
|
|
|
|
|
} |
|
|
|
|
|
], |
|
|
|
|
|
maxActivitiesToImport: 1 |
|
|
|
|
|
}); |
|
|
}); |
|
|
} catch (error) { |
|
|
|
|
|
throw new HttpException( |
|
|
|
|
|
{ |
|
|
|
|
|
error: getReasonPhrase(StatusCodes.BAD_REQUEST), |
|
|
|
|
|
message: [error.message] |
|
|
|
|
|
}, |
|
|
|
|
|
StatusCodes.BAD_REQUEST |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const currency = data.currency; |
|
|
const currency = data.currency; |
|
|
const customCurrency = data.customCurrency; |
|
|
const customCurrency = data.customCurrency; |
|
|
@ -344,7 +323,12 @@ export class ActivitiesController { |
|
|
@UseInterceptors(TransformDataSourceInRequestInterceptor) |
|
|
@UseInterceptors(TransformDataSourceInRequestInterceptor) |
|
|
public async updateActivity( |
|
|
public async updateActivity( |
|
|
@Body() data: UpdateOrderDto, |
|
|
@Body() data: UpdateOrderDto, |
|
|
@Impersonation() { userId }: ImpersonationContext, |
|
|
@Impersonation() |
|
|
|
|
|
{ |
|
|
|
|
|
authenticatedUserSubscription, |
|
|
|
|
|
userId, |
|
|
|
|
|
userSubscription |
|
|
|
|
|
}: ImpersonationContext, |
|
|
@Param('id') id: string |
|
|
@Param('id') id: string |
|
|
): Promise<UpdateActivityResponse> { |
|
|
): Promise<UpdateActivityResponse> { |
|
|
const originalActivity = await this.activitiesService.order({ |
|
|
const originalActivity = await this.activitiesService.order({ |
|
|
@ -359,6 +343,29 @@ export class ActivitiesController { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const isAssetProfileConnected = |
|
|
|
|
|
!NON_INVESTMENT_ACTIVITY_TYPES.includes(data.type) && |
|
|
|
|
|
!(data.dataSource === 'MANUAL' && data.type === 'BUY'); |
|
|
|
|
|
|
|
|
|
|
|
if (isAssetProfileConnected) { |
|
|
|
|
|
const [originalAssetProfile] = |
|
|
|
|
|
await this.symbolProfileService.getSymbolProfilesByIds([ |
|
|
|
|
|
originalActivity.symbolProfileId |
|
|
|
|
|
]); |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
originalAssetProfile.dataSource !== data.dataSource || |
|
|
|
|
|
originalAssetProfile.symbol !== data.symbol |
|
|
|
|
|
) { |
|
|
|
|
|
await this.validateActivity({ |
|
|
|
|
|
authenticatedUserSubscription, |
|
|
|
|
|
userId, |
|
|
|
|
|
userSubscription, |
|
|
|
|
|
activityDto: data |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const date = parseISO(data.date); |
|
|
const date = parseISO(data.date); |
|
|
|
|
|
|
|
|
const accountId = data.accountId; |
|
|
const accountId = data.accountId; |
|
|
@ -428,4 +435,43 @@ export class ActivitiesController { |
|
|
'userId' |
|
|
'userId' |
|
|
]); |
|
|
]); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async validateActivity({ |
|
|
|
|
|
activityDto: { currency, dataSource, symbol, type }, |
|
|
|
|
|
authenticatedUserSubscription, |
|
|
|
|
|
userId, |
|
|
|
|
|
userSubscription |
|
|
|
|
|
}: Pick< |
|
|
|
|
|
ImpersonationContext, |
|
|
|
|
|
'authenticatedUserSubscription' | 'userId' | 'userSubscription' |
|
|
|
|
|
> & { |
|
|
|
|
|
activityDto: Pick< |
|
|
|
|
|
CreateOrderDto, |
|
|
|
|
|
'currency' | 'dataSource' | 'symbol' | 'type' |
|
|
|
|
|
>; |
|
|
|
|
|
}) { |
|
|
|
|
|
// Evaluate the more restrictive subscription of the authenticated user
|
|
|
|
|
|
// and the owner of the activity
|
|
|
|
|
|
const subscription = |
|
|
|
|
|
userSubscription?.type === SubscriptionType.Basic |
|
|
|
|
|
? userSubscription |
|
|
|
|
|
: authenticatedUserSubscription; |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
await this.dataProviderService.validateActivities({ |
|
|
|
|
|
subscription, |
|
|
|
|
|
userId, |
|
|
|
|
|
activitiesDto: [{ currency, dataSource, symbol, type }], |
|
|
|
|
|
maxActivitiesToImport: 1 |
|
|
|
|
|
}); |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
throw new HttpException( |
|
|
|
|
|
{ |
|
|
|
|
|
error: getReasonPhrase(StatusCodes.BAD_REQUEST), |
|
|
|
|
|
message: [error.message] |
|
|
|
|
|
}, |
|
|
|
|
|
StatusCodes.BAD_REQUEST |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|