Browse Source

Fix unused custom asset profiles created by activities import

pull/7673/head
Thomas Kaul 1 week ago
parent
commit
414c173044
  1. 34
      apps/api/src/app/import/import.helper.ts
  2. 62
      apps/api/src/app/import/import.service.ts
  3. 6
      apps/api/src/app/import/interfaces/interfaces.ts
  4. 6
      apps/api/src/services/data-provider/data-provider.service.ts

34
apps/api/src/app/import/import.helper.ts

@ -0,0 +1,34 @@
import { getAssetProfileIdentifier } from '@ghostfolio/common/helper';
import { Activity } from '@ghostfolio/common/interfaces';
import { AssetProfileToCreate } from './interfaces/interfaces';
/**
* Returns the asset profiles which at least one activity of the import uses.
* The asset profiles are created after the validation of the activities,
* thus an asset profile of an activity which is not imported must not be
* created.
*/
export function getAssetProfilesToCreate({
activities,
assetProfiles
}: {
activities: Partial<Activity>[];
assetProfiles: AssetProfileToCreate[];
}) {
const assetProfileIdentifiersToImport = new Set(
activities
.filter(({ error }) => {
return !error;
})
.map(({ assetProfile }) => {
return getAssetProfileIdentifier(assetProfile);
})
);
return assetProfiles.filter(({ assetProfile }) => {
return assetProfileIdentifiersToImport.has(
getAssetProfileIdentifier(assetProfile)
);
});
}

62
apps/api/src/app/import/import.service.ts

@ -48,6 +48,8 @@ import { omit, uniqBy } from 'lodash';
import { randomUUID } from 'node:crypto';
import { ImportDataDto } from './import-data.dto';
import { getAssetProfilesToCreate } from './import.helper';
import { AssetProfileToCreate } from './interfaces/interfaces';
@Injectable()
export class ImportService {
@ -534,10 +536,7 @@ export class ImportService {
}
}
const assetProfilesToCreate: {
assetProfile: Prisma.SymbolProfileCreateInput;
marketDataObjects: Prisma.MarketDataUpdateInput[];
}[] = [];
const assetProfilesToCreate: AssetProfileToCreate[] = [];
if (assetProfilesWithMarketDataDto?.length) {
const customAssetProfileNames = assetProfilesWithMarketDataDto
@ -738,16 +737,18 @@ export class ImportService {
// duplicate. An asset profile which is created before the validation of
// the activities would stay behind, because the import is not rolled back
// on an error.
for (const {
assetProfile,
marketDataObjects
} of this.getAssetProfilesToCreate({
activities: activitiesExtendedWithErrors,
assetProfiles: assetProfilesToCreate
})) {
await this.symbolProfileService.add(assetProfile);
await this.marketDataService.updateMany({ data: marketDataObjects });
if (!isDryRun) {
for (const {
assetProfile,
marketDataObjects
} of getAssetProfilesToCreate({
activities: activitiesExtendedWithErrors,
assetProfiles: assetProfilesToCreate
})) {
await this.symbolProfileService.add(assetProfile);
await this.marketDataService.updateMany({ data: marketDataObjects });
}
}
const activities: Activity[] = [];
@ -1086,39 +1087,6 @@ export class ImportService {
return matchingAccountsOfUser[0];
}
/**
* Returns the asset profiles which at least one activity of the import uses.
* The asset profiles are created after the validation of the activities,
* thus an asset profile of an activity which is not imported must not be
* created.
*/
private getAssetProfilesToCreate({
activities,
assetProfiles
}: {
activities: Partial<Activity>[];
assetProfiles: {
assetProfile: Prisma.SymbolProfileCreateInput;
marketDataObjects: Prisma.MarketDataUpdateInput[];
}[];
}) {
const assetProfileIdentifiersToImport = new Set(
activities
.filter(({ error }) => {
return !error;
})
.map(({ assetProfile }) => {
return getAssetProfileIdentifier(assetProfile);
})
);
return assetProfiles.filter(({ assetProfile }) => {
return assetProfileIdentifiersToImport.has(
getAssetProfileIdentifier(assetProfile)
);
});
}
private isUniqueAccount(accounts: AccountWithValue[]) {
const uniqueAccountIds = new Set<string>();

6
apps/api/src/app/import/interfaces/interfaces.ts

@ -0,0 +1,6 @@
import { Prisma } from '@prisma/client';
export interface AssetProfileToCreate {
assetProfile: Prisma.SymbolProfileCreateInput;
marketDataObjects: Prisma.MarketDataUpdateInput[];
}

6
apps/api/src/services/data-provider/data-provider.service.ts

@ -273,10 +273,10 @@ export class DataProviderService implements OnModuleInit {
if (!assetProfiles[assetProfileIdentifier]) {
const assetProfileInImport = assetProfilesWithMarketDataDto?.find(
(assetProfile) => {
(assetProfileWithMarketData) => {
return (
assetProfile.dataSource === dataSource &&
assetProfile.symbol === symbol
assetProfileWithMarketData.dataSource === dataSource &&
assetProfileWithMarketData.symbol === symbol
);
}
);

Loading…
Cancel
Save