|
|
@ -11,11 +11,13 @@ import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/sy |
|
|
import { TagService } from '@ghostfolio/api/services/tag/tag.service'; |
|
|
import { TagService } from '@ghostfolio/api/services/tag/tag.service'; |
|
|
import { |
|
|
import { |
|
|
ACTIVITY_TYPES_WITH_GENERATED_UUID_SYMBOL, |
|
|
ACTIVITY_TYPES_WITH_GENERATED_UUID_SYMBOL, |
|
|
DATA_GATHERING_QUEUE_PRIORITY_HIGH |
|
|
DATA_GATHERING_QUEUE_PRIORITY_HIGH, |
|
|
|
|
|
ghostfolioPrefix |
|
|
} from '@ghostfolio/common/config'; |
|
|
} from '@ghostfolio/common/config'; |
|
|
import { CreateAssetProfileDto, CreateOrderDto } from '@ghostfolio/common/dtos'; |
|
|
import { CreateAssetProfileDto, CreateOrderDto } from '@ghostfolio/common/dtos'; |
|
|
import { |
|
|
import { |
|
|
getAssetProfileIdentifier, |
|
|
getAssetProfileIdentifier, |
|
|
|
|
|
isGhostfolioSymbol, |
|
|
parseDate |
|
|
parseDate |
|
|
} from '@ghostfolio/common/helper'; |
|
|
} from '@ghostfolio/common/helper'; |
|
|
import { |
|
|
import { |
|
|
@ -34,7 +36,7 @@ import { Injectable } from '@nestjs/common'; |
|
|
import { DataSource, Prisma } from '@prisma/client'; |
|
|
import { DataSource, Prisma } from '@prisma/client'; |
|
|
import { Big } from 'big.js'; |
|
|
import { Big } from 'big.js'; |
|
|
import { endOfToday, isAfter, isSameSecond, parseISO } from 'date-fns'; |
|
|
import { endOfToday, isAfter, isSameSecond, parseISO } from 'date-fns'; |
|
|
import { omit, uniqBy } from 'lodash'; |
|
|
import { omit, uniq, 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'; |
|
|
@ -193,6 +195,11 @@ export class ImportService { |
|
|
const tagIdMapping: { [oldTagId: string]: string } = {}; |
|
|
const tagIdMapping: { [oldTagId: string]: string } = {}; |
|
|
const userCurrency = user.settings.settings.baseCurrency; |
|
|
const userCurrency = user.settings.settings.baseCurrency; |
|
|
|
|
|
|
|
|
|
|
|
await this.validateGhostfolioSymbols({ |
|
|
|
|
|
activitiesDto, |
|
|
|
|
|
assetProfilesWithMarketDataDto |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
const existingTagsOfUser = |
|
|
const existingTagsOfUser = |
|
|
tagsDto?.length || (!isDryRun && accountsWithBalancesDto?.length) |
|
|
tagsDto?.length || (!isDryRun && accountsWithBalancesDto?.length) |
|
|
? await this.tagService.getTagsForUser(user.id) |
|
|
? await this.tagService.getTagsForUser(user.id) |
|
|
@ -749,4 +756,45 @@ export class ImportService { |
|
|
|
|
|
|
|
|
return uniqueAccountIds.size === 1; |
|
|
return uniqueAccountIds.size === 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async validateGhostfolioSymbols({ |
|
|
|
|
|
activitiesDto, |
|
|
|
|
|
assetProfilesWithMarketDataDto |
|
|
|
|
|
}: { |
|
|
|
|
|
activitiesDto: ImportDataDto['activities']; |
|
|
|
|
|
assetProfilesWithMarketDataDto: ImportDataDto['assetProfiles']; |
|
|
|
|
|
}) { |
|
|
|
|
|
const symbols = uniq( |
|
|
|
|
|
[...(activitiesDto ?? []), ...(assetProfilesWithMarketDataDto ?? [])].map( |
|
|
|
|
|
({ symbol }) => { |
|
|
|
|
|
return symbol; |
|
|
|
|
|
} |
|
|
|
|
|
) |
|
|
|
|
|
).filter((symbol) => { |
|
|
|
|
|
return isGhostfolioSymbol(symbol); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (symbols.length === 0) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const existingAssetProfiles = |
|
|
|
|
|
await this.symbolProfileService.getSymbolProfiles( |
|
|
|
|
|
symbols.map((symbol) => { |
|
|
|
|
|
return { symbol, dataSource: DataSource.MANUAL }; |
|
|
|
|
|
}) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const missingSymbols = symbols.filter((symbol) => { |
|
|
|
|
|
return !existingAssetProfiles.some(({ symbol: existingSymbol }) => { |
|
|
|
|
|
return existingSymbol === symbol; |
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (missingSymbols.length > 0) { |
|
|
|
|
|
throw new Error( |
|
|
|
|
|
`Asset profiles with the prefix "${ghostfolioPrefix}_" can only be created in the admin control (${missingSymbols.join(', ')})` |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|