Browse Source

Fix data gathering of manual activities

pull/7997/head
Thomas Kaul 2 weeks ago
parent
commit
73e8fb38ad
  1. 11
      apps/api/src/app/activities/activities.controller.ts
  2. 15
      apps/api/src/helper/data-source.helper.ts
  3. 22
      apps/api/src/services/queues/data-gathering/data-gathering.service.ts

11
apps/api/src/app/activities/activities.controller.ts

@ -2,6 +2,7 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorat
import { Impersonation } from '@ghostfolio/api/decorators/impersonation.decorator';
import { RequiresScope } from '@ghostfolio/api/decorators/requires-scope.decorator';
import { isActivityInFuture } from '@ghostfolio/api/helper/activity.helper';
import { isDataGatheringSupported } from '@ghostfolio/api/helper/data-source.helper';
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor';
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor';
@ -32,7 +33,7 @@ import {
Query,
UseInterceptors
} from '@nestjs/common';
import { Order } from '@prisma/client';
import { Order, Prisma } from '@prisma/client';
import { parseISO } from 'date-fns';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
@ -216,7 +217,7 @@ export class ActivitiesController {
userId,
userSubscription
}: ImpersonationContext
): Promise<Order> {
): Promise<Prisma.OrderGetPayload<{ include: { SymbolProfile: true } }>> {
// Evaluate the more restrictive subscription of the authenticated user
// and the owner of the activity
const subscription =
@ -285,11 +286,11 @@ export class ActivitiesController {
});
if (
activity.SymbolProfile.dataSource !== 'MANUAL' &&
isDataGatheringSupported(activity.SymbolProfile) &&
!isActivityInFuture({ date: activity.date })
) {
// Gather symbol data in the background, if the data source is not
// MANUAL and the date is not in the future
// Gather symbol data in the background, if the asset profile supports
// data gathering and the date is not in the future
this.dataGatheringService.gatherSymbols({
dataGatheringItems: [
{

15
apps/api/src/helper/data-source.helper.ts

@ -1,6 +1,7 @@
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { DataSource } from '@prisma/client';
import { DataSource, Prisma } from '@prisma/client';
import { isEmpty } from 'lodash-es';
import { createHash } from 'node:crypto';
const DATA_SOURCES_WITHOUT_ENCODING: DataSource[] = [
@ -95,6 +96,18 @@ export function getUnmaskedGhostfolioDataSource({
: dataSource;
}
export function isDataGatheringSupported({
dataSource,
scraperConfiguration
}: {
dataSource: DataSource;
scraperConfiguration: Prisma.JsonValue;
}) {
// An asset profile with the MANUAL data source supports data gathering only
// with a scraper configuration
return dataSource !== DataSource.MANUAL || !isEmpty(scraperConfiguration);
}
export function isDataSourceEncodedInResponse(dataSource: DataSource) {
return !DATA_SOURCES_WITHOUT_ENCODING.includes(dataSource);
}

22
apps/api/src/services/queues/data-gathering/data-gathering.service.ts

@ -1,3 +1,4 @@
import { isDataGatheringSupported } from '@ghostfolio/api/helper/data-source.helper';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { DataEnhancerInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-enhancer.interface';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
@ -33,7 +34,6 @@ import { Inject, Injectable, Logger } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { Job, JobOptions, Queue } from 'bull';
import { format, min, subDays, subMilliseconds, subYears } from 'date-fns';
import { isEmpty } from 'lodash-es';
import ms, { StringValue } from 'ms';
@Injectable()
@ -506,12 +506,7 @@ export class DataGatheringService {
return symbolProfiles
.filter(({ dataSource, scraperConfiguration }) => {
const manualDataSourceWithScraperConfiguration =
dataSource === 'MANUAL' && !isEmpty(scraperConfiguration);
return (
dataSource !== 'MANUAL' || manualDataSourceWithScraperConfiguration
);
return isDataGatheringSupported({ dataSource, scraperConfiguration });
})
.map(({ dataSource, symbol }) => {
return { dataSource, symbol };
@ -534,14 +529,10 @@ export class DataGatheringService {
return symbolProfiles
.filter(({ dataSource, scraperConfiguration, symbol }) => {
const manualDataSourceWithScraperConfiguration =
dataSource === 'MANUAL' && !isEmpty(scraperConfiguration);
return (
!assetProfileIdentifiersWithRecentMarketData.some((item) => {
return item.dataSource === dataSource && item.symbol === symbol;
}) &&
(dataSource !== 'MANUAL' || manualDataSourceWithScraperConfiguration)
}) && isDataGatheringSupported({ dataSource, scraperConfiguration })
);
})
.map((symbolProfile) => {
@ -598,12 +589,7 @@ export class DataGatheringService {
})
)
.filter(({ dataSource, scraperConfiguration }) => {
const manualDataSourceWithScraperConfiguration =
dataSource === 'MANUAL' && !isEmpty(scraperConfiguration);
return (
dataSource !== 'MANUAL' || manualDataSourceWithScraperConfiguration
);
return isDataGatheringSupported({ dataSource, scraperConfiguration });
})
.map((symbolProfile) => {
let date = symbolProfile.activities?.[0]?.date ?? startDate;

Loading…
Cancel
Save