mirror of https://github.com/ghostfolio/ghostfolio
5 changed files with 137 additions and 3 deletions
@ -0,0 +1,46 @@ |
|||||
|
import { |
||||
|
ValidationArguments, |
||||
|
ValidatorConstraint, |
||||
|
ValidatorConstraintInterface |
||||
|
} from 'class-validator'; |
||||
|
|
||||
|
import { ghostfolioPrefix } from '../config'; |
||||
|
import { isValidManualSymbol } from '../helper'; |
||||
|
|
||||
|
interface ImportDataLike { |
||||
|
activities?: { dataSource?: string; symbol?: string; type?: string }[]; |
||||
|
assetProfiles?: { dataSource?: string; symbol?: string }[]; |
||||
|
} |
||||
|
|
||||
|
@ValidatorConstraint({ name: 'hasValidManualSymbols' }) |
||||
|
export class HasValidManualSymbolsConstraint implements ValidatorConstraintInterface { |
||||
|
public defaultMessage() { |
||||
|
return `manual symbols must be a UUID or start with "${ghostfolioPrefix}_"`; |
||||
|
} |
||||
|
|
||||
|
public validate(_: unknown, args: ValidationArguments) { |
||||
|
const { activities = [], assetProfiles = [] } = |
||||
|
args.object as ImportDataLike; |
||||
|
|
||||
|
const activitiesAreValid = activities.every( |
||||
|
({ dataSource, symbol, type }) => { |
||||
|
// FEE, INTEREST and LIABILITY default to the MANUAL data source
|
||||
|
// (resolved in the backend), so treat them as manual when no data
|
||||
|
// source is set
|
||||
|
const isManual = |
||||
|
dataSource === 'MANUAL' || |
||||
|
(!dataSource && ['FEE', 'INTEREST', 'LIABILITY'].includes(type)); |
||||
|
|
||||
|
return !isManual || isValidManualSymbol(symbol); |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
const assetProfilesAreValid = assetProfiles.every( |
||||
|
({ dataSource, symbol }) => { |
||||
|
return dataSource !== 'MANUAL' || isValidManualSymbol(symbol); |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
return activitiesAreValid && assetProfilesAreValid; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
{ |
||||
|
"meta": { |
||||
|
"date": "2023-02-05T00:00:00.000Z", |
||||
|
"version": "dev" |
||||
|
}, |
||||
|
"accounts": [], |
||||
|
"assetProfiles": [ |
||||
|
{ |
||||
|
"assetClass": null, |
||||
|
"assetSubClass": null, |
||||
|
"comment": null, |
||||
|
"countries": [], |
||||
|
"currency": "USD", |
||||
|
"cusip": null, |
||||
|
"dataSource": "MANUAL", |
||||
|
"figi": null, |
||||
|
"figiComposite": null, |
||||
|
"figiShareClass": null, |
||||
|
"holdings": [], |
||||
|
"isActive": true, |
||||
|
"isin": null, |
||||
|
"marketData": [], |
||||
|
"name": "Penthouse Apartment", |
||||
|
"sectors": [], |
||||
|
"symbol": "PENTHOUSE_APARTMENT", |
||||
|
"url": null |
||||
|
} |
||||
|
], |
||||
|
"platforms": [], |
||||
|
"tags": [], |
||||
|
"activities": [ |
||||
|
{ |
||||
|
"accountId": null, |
||||
|
"comment": null, |
||||
|
"currency": "USD", |
||||
|
"dataSource": "MANUAL", |
||||
|
"date": "2022-01-01T00:00:00.000Z", |
||||
|
"fee": 0, |
||||
|
"quantity": 1, |
||||
|
"symbol": "PENTHOUSE_APARTMENT", |
||||
|
"tags": [], |
||||
|
"type": "BUY", |
||||
|
"unitPrice": 500000 |
||||
|
} |
||||
|
], |
||||
|
"user": { |
||||
|
"settings": { |
||||
|
"currency": "USD", |
||||
|
"performanceCalculationType": "ROAI" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue