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. 44
      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)
);
});
}

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

@ -48,6 +48,8 @@ import { omit, uniqBy } from 'lodash';
import { randomUUID } from 'node:crypto'; import { randomUUID } from 'node:crypto';
import { ImportDataDto } from './import-data.dto'; import { ImportDataDto } from './import-data.dto';
import { getAssetProfilesToCreate } from './import.helper';
import { AssetProfileToCreate } from './interfaces/interfaces';
@Injectable() @Injectable()
export class ImportService { export class ImportService {
@ -534,10 +536,7 @@ export class ImportService {
} }
} }
const assetProfilesToCreate: { const assetProfilesToCreate: AssetProfileToCreate[] = [];
assetProfile: Prisma.SymbolProfileCreateInput;
marketDataObjects: Prisma.MarketDataUpdateInput[];
}[] = [];
if (assetProfilesWithMarketDataDto?.length) { if (assetProfilesWithMarketDataDto?.length) {
const customAssetProfileNames = assetProfilesWithMarketDataDto const customAssetProfileNames = assetProfilesWithMarketDataDto
@ -738,10 +737,11 @@ export class ImportService {
// duplicate. An asset profile which is created before the validation of // duplicate. An asset profile which is created before the validation of
// the activities would stay behind, because the import is not rolled back // the activities would stay behind, because the import is not rolled back
// on an error. // on an error.
if (!isDryRun) {
for (const { for (const {
assetProfile, assetProfile,
marketDataObjects marketDataObjects
} of this.getAssetProfilesToCreate({ } of getAssetProfilesToCreate({
activities: activitiesExtendedWithErrors, activities: activitiesExtendedWithErrors,
assetProfiles: assetProfilesToCreate assetProfiles: assetProfilesToCreate
})) { })) {
@ -749,6 +749,7 @@ export class ImportService {
await this.marketDataService.updateMany({ data: marketDataObjects }); await this.marketDataService.updateMany({ data: marketDataObjects });
} }
}
const activities: Activity[] = []; const activities: Activity[] = [];
@ -1086,39 +1087,6 @@ export class ImportService {
return matchingAccountsOfUser[0]; 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[]) { private isUniqueAccount(accounts: AccountWithValue[]) {
const uniqueAccountIds = new Set<string>(); 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]) { if (!assetProfiles[assetProfileIdentifier]) {
const assetProfileInImport = assetProfilesWithMarketDataDto?.find( const assetProfileInImport = assetProfilesWithMarketDataDto?.find(
(assetProfile) => { (assetProfileWithMarketData) => {
return ( return (
assetProfile.dataSource === dataSource && assetProfileWithMarketData.dataSource === dataSource &&
assetProfile.symbol === symbol assetProfileWithMarketData.symbol === symbol
); );
} }
); );

Loading…
Cancel
Save