Browse Source

Feature/deprecate ITEM activity type in favor of BUY (#5093)

* Deprecate ITEM activity type in favor of BUY

* Update changelog
pull/5097/head
Thomas Kaul 2 weeks ago
committed by GitHub
parent
commit
55e4d2fc7a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 25
      README.md
  3. 8
      apps/api/src/app/export/export.service.ts
  4. 14
      apps/api/src/app/import/import.service.ts
  5. 16
      apps/api/src/app/order/order.controller.ts
  6. 31
      apps/api/src/app/order/order.service.ts
  7. 30
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  8. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts
  9. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts
  10. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts
  11. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts
  12. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts
  13. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts
  14. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts
  15. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts
  16. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts
  17. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts
  18. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts
  19. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts
  20. 33
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-valuable.spec.ts
  21. 22
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts
  22. 1
      apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts
  23. 4
      apps/api/src/app/portfolio/portfolio.service.ts
  24. 12
      apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html
  25. 29
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  26. 2
      apps/client/src/app/services/import-activities.service.ts
  27. 1
      libs/common/src/lib/interfaces/portfolio-summary.interface.ts
  28. 2
      libs/common/src/lib/interfaces/symbol-metrics.interface.ts
  29. 4
      libs/common/src/lib/models/portfolio-snapshot.ts
  30. 3
      libs/ui/src/lib/activity-type/activity-type.component.html
  31. 4
      libs/ui/src/lib/activity-type/activity-type.component.scss
  32. 2
      prisma/migrations/20250704214021_changed_type_from_item_to_buy_in_order/migration.sql
  33. 20
      test/import/not-ok/invalid-type-deprecated.json
  34. 2
      test/import/ok/sample.csv
  35. 2
      test/import/ok/sample.json
  36. 2
      test/import/ok/without-accounts.json

1
CHANGELOG.md

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Increased the width of the markets overview - Increased the width of the markets overview
- Increased the width of the watchlist - Increased the width of the watchlist
- Deprecated the `ITEM` activity type in favor of `BUY`
- Renamed `Access` to `accessesGet` in the `User` database schema - Renamed `Access` to `accessesGet` in the `User` database schema
- Improved the language localization for Dutch (`nl`) - Improved the language localization for Dutch (`nl`)
- Improved the language localization for Italian (`it`) - Improved the language localization for Italian (`it`)

25
README.md

@ -138,7 +138,6 @@ docker compose -f docker/docker-compose.build.yml up -d
#### Upgrade Version #### Upgrade Version
1. Update the _Ghostfolio_ Docker image 1. Update the _Ghostfolio_ Docker image
- Increase the version of the `ghostfolio/ghostfolio` Docker image in `docker/docker-compose.yml` - Increase the version of the `ghostfolio/ghostfolio` Docker image in `docker/docker-compose.yml`
- Run the following command if `ghostfolio:latest` is set: - Run the following command if `ghostfolio:latest` is set:
```bash ```bash
@ -222,18 +221,18 @@ Deprecated: `GET http://localhost:3333/api/v1/auth/anonymous/<INSERT_SECURITY_TO
} }
``` ```
| Field | Type | Description | | Field | Type | Description |
| ------------ | ------------------- | ----------------------------------------------------------------------------- | | ------------ | ------------------- | ------------------------------------------------------------------- |
| `accountId` | `string` (optional) | Id of the account | | `accountId` | `string` (optional) | Id of the account |
| `comment` | `string` (optional) | Comment of the activity | | `comment` | `string` (optional) | Comment of the activity |
| `currency` | `string` | `CHF` \| `EUR` \| `USD` etc. | | `currency` | `string` | `CHF` \| `EUR` \| `USD` etc. |
| `dataSource` | `string` | `COINGECKO` \| `MANUAL` (for type `ITEM`) \| `YAHOO` | | `dataSource` | `string` | `COINGECKO` \| `MANUAL` \| `YAHOO` |
| `date` | `string` | Date in the format `ISO-8601` | | `date` | `string` | Date in the format `ISO-8601` |
| `fee` | `number` | Fee of the activity | | `fee` | `number` | Fee of the activity |
| `quantity` | `number` | Quantity of the activity | | `quantity` | `number` | Quantity of the activity |
| `symbol` | `string` | Symbol of the activity (suitable for `dataSource`) | | `symbol` | `string` | Symbol of the activity (suitable for `dataSource`) |
| `type` | `string` | `BUY` \| `DIVIDEND` \| `FEE` \| `INTEREST` \| `ITEM` \| `LIABILITY` \| `SELL` | | `type` | `string` | `BUY` \| `DIVIDEND` \| `FEE` \| `INTEREST` \| `LIABILITY` \| `SELL` |
| `unitPrice` | `number` | Price per unit of the activity | | `unitPrice` | `number` | Price per unit of the activity |
#### Response #### Response

8
apps/api/src/app/export/export.service.ts

@ -141,9 +141,11 @@ export class ExportService {
currency: currency ?? SymbolProfile.currency, currency: currency ?? SymbolProfile.currency,
dataSource: SymbolProfile.dataSource, dataSource: SymbolProfile.dataSource,
date: date.toISOString(), date: date.toISOString(),
symbol: ['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(type) symbol:
? SymbolProfile.name ['FEE', 'INTEREST', 'LIABILITY'].includes(type) ||
: SymbolProfile.symbol, (SymbolProfile.dataSource === 'MANUAL' && type === 'BUY')
? SymbolProfile.name
: SymbolProfile.symbol,
tags: currentTags.map(({ id: tagId }) => { tags: currentTags.map(({ id: tagId }) => {
return tagId; return tagId;
}) })

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

@ -232,7 +232,7 @@ export class ImportService {
for (const activity of activitiesDto) { for (const activity of activitiesDto) {
if (!activity.dataSource) { if (!activity.dataSource) {
if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(activity.type)) { if (['FEE', 'INTEREST', 'LIABILITY'].includes(activity.type)) {
activity.dataSource = DataSource.MANUAL; activity.dataSource = DataSource.MANUAL;
} else { } else {
activity.dataSource = activity.dataSource =
@ -564,6 +564,12 @@ export class ImportService {
index, index,
{ currency, dataSource, symbol, type } { currency, dataSource, symbol, type }
] of activitiesDto.entries()) { ] of activitiesDto.entries()) {
if (type === 'ITEM') {
throw new Error(
`activities.${index}.type ("${type}") is deprecated, please use "BUY" instead`
);
}
if (!dataSources.includes(dataSource)) { if (!dataSources.includes(dataSource)) {
throw new Error( throw new Error(
`activities.${index}.dataSource ("${dataSource}") is not valid` `activities.${index}.dataSource ("${dataSource}") is not valid`
@ -595,7 +601,11 @@ export class ImportService {
)?.[symbol] )?.[symbol]
}; };
if (type === 'BUY' || type === 'DIVIDEND' || type === 'SELL') { if (
(dataSource !== 'MANUAL' && type === 'BUY') ||
type === 'DIVIDEND' ||
type === 'SELL'
) {
if (!assetProfile?.name) { if (!assetProfile?.name) {
throw new Error( throw new Error(
`activities.${index}.symbol ("${symbol}") is not valid for the specified data source ("${dataSource}")` `activities.${index}.symbol ("${symbol}") is not valid for the specified data source ("${dataSource}")`

16
apps/api/src/app/order/order.controller.ts

@ -189,6 +189,7 @@ export class OrderController {
public async createOrder(@Body() data: CreateOrderDto): Promise<OrderModel> { public async createOrder(@Body() data: CreateOrderDto): Promise<OrderModel> {
const currency = data.currency; const currency = data.currency;
const customCurrency = data.customCurrency; const customCurrency = data.customCurrency;
const dataSource = data.dataSource;
if (customCurrency) { if (customCurrency) {
data.currency = customCurrency; data.currency = customCurrency;
@ -196,6 +197,8 @@ export class OrderController {
delete data.customCurrency; delete data.customCurrency;
} }
delete data.dataSource;
const order = await this.orderService.createOrder({ const order = await this.orderService.createOrder({
...data, ...data,
date: parseISO(data.date), date: parseISO(data.date),
@ -203,12 +206,12 @@ export class OrderController {
connectOrCreate: { connectOrCreate: {
create: { create: {
currency, currency,
dataSource: data.dataSource, dataSource,
symbol: data.symbol symbol: data.symbol
}, },
where: { where: {
dataSource_symbol: { dataSource_symbol: {
dataSource: data.dataSource, dataSource,
symbol: data.symbol symbol: data.symbol
} }
} }
@ -218,13 +221,13 @@ export class OrderController {
userId: this.request.user.id userId: this.request.user.id
}); });
if (data.dataSource && !order.isDraft) { if (dataSource && !order.isDraft) {
// Gather symbol data in the background, if data source is set // Gather symbol data in the background, if data source is set
// (not MANUAL) and not draft // (not MANUAL) and not draft
this.dataGatheringService.gatherSymbols({ this.dataGatheringService.gatherSymbols({
dataGatheringItems: [ dataGatheringItems: [
{ {
dataSource: data.dataSource, dataSource,
date: order.date, date: order.date,
symbol: data.symbol symbol: data.symbol
} }
@ -256,6 +259,7 @@ export class OrderController {
const accountId = data.accountId; const accountId = data.accountId;
const customCurrency = data.customCurrency; const customCurrency = data.customCurrency;
const dataSource = data.dataSource;
delete data.accountId; delete data.accountId;
@ -265,6 +269,8 @@ export class OrderController {
delete data.customCurrency; delete data.customCurrency;
} }
delete data.dataSource;
return this.orderService.updateOrder({ return this.orderService.updateOrder({
data: { data: {
...data, ...data,
@ -277,7 +283,7 @@ export class OrderController {
SymbolProfile: { SymbolProfile: {
connect: { connect: {
dataSource_symbol: { dataSource_symbol: {
dataSource: data.dataSource, dataSource,
symbol: data.symbol symbol: data.symbol
} }
}, },

31
apps/api/src/app/order/order.service.ts

@ -93,7 +93,6 @@ export class OrderService {
assetClass?: AssetClass; assetClass?: AssetClass;
assetSubClass?: AssetSubClass; assetSubClass?: AssetSubClass;
currency?: string; currency?: string;
dataSource?: DataSource;
symbol?: string; symbol?: string;
tags?: Tag[]; tags?: Tag[];
updateAccountBalance?: boolean; updateAccountBalance?: boolean;
@ -118,7 +117,11 @@ export class OrderService {
const updateAccountBalance = data.updateAccountBalance ?? false; const updateAccountBalance = data.updateAccountBalance ?? false;
const userId = data.userId; const userId = data.userId;
if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type)) { if (
['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) ||
(data.SymbolProfile.connectOrCreate.create.dataSource === 'MANUAL' &&
data.type === 'BUY')
) {
const assetClass = data.assetClass; const assetClass = data.assetClass;
const assetSubClass = data.assetSubClass; const assetSubClass = data.assetSubClass;
const dataSource: DataSource = 'MANUAL'; const dataSource: DataSource = 'MANUAL';
@ -164,7 +167,6 @@ export class OrderService {
delete data.comment; delete data.comment;
} }
delete data.dataSource;
delete data.symbol; delete data.symbol;
delete data.tags; delete data.tags;
delete data.updateAccountBalance; delete data.updateAccountBalance;
@ -172,7 +174,7 @@ export class OrderService {
const orderData: Prisma.OrderCreateInput = data; const orderData: Prisma.OrderCreateInput = data;
const isDraft = ['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type) const isDraft = ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type)
? false ? false
: isAfter(data.date as Date, endOfToday()); : isAfter(data.date as Date, endOfToday());
@ -631,7 +633,6 @@ export class OrderService {
assetClass?: AssetClass; assetClass?: AssetClass;
assetSubClass?: AssetSubClass; assetSubClass?: AssetSubClass;
currency?: string; currency?: string;
dataSource?: DataSource;
symbol?: string; symbol?: string;
tags?: Tag[]; tags?: Tag[];
type?: ActivityType; type?: ActivityType;
@ -646,12 +647,17 @@ export class OrderService {
let isDraft = false; let isDraft = false;
if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type)) { if (
delete data.SymbolProfile.connect; ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) ||
(data.SymbolProfile.connect.dataSource_symbol.dataSource === 'MANUAL' &&
data.type === 'BUY')
) {
if (data.account?.connect?.id_userId?.id === null) { if (data.account?.connect?.id_userId?.id === null) {
data.account = { disconnect: true }; data.account = { disconnect: true };
} }
delete data.SymbolProfile.connect;
delete data.SymbolProfile.update.name;
} else { } else {
delete data.SymbolProfile.update; delete data.SymbolProfile.update;
@ -675,17 +681,17 @@ export class OrderService {
delete data.assetClass; delete data.assetClass;
delete data.assetSubClass; delete data.assetSubClass;
delete data.dataSource;
delete data.symbol; delete data.symbol;
delete data.tags; delete data.tags;
// Remove existing tags // Remove existing tags
await this.prismaService.order.update({ await this.prismaService.order.update({
data: { tags: { set: [] } }, where,
where data: { tags: { set: [] } }
}); });
const order = await this.prismaService.order.update({ const order = await this.prismaService.order.update({
where,
data: { data: {
...data, ...data,
isDraft, isDraft,
@ -694,8 +700,7 @@ export class OrderService {
return { id }; return { id };
}) })
} }
}, }
where
}); });
this.eventEmitter.emit( this.eventEmitter.emit(

30
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -187,8 +187,7 @@ export abstract class PortfolioCalculator {
totalInterestWithCurrencyEffect: new Big(0), totalInterestWithCurrencyEffect: new Big(0),
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0),
totalLiabilitiesWithCurrencyEffect: new Big(0), totalLiabilitiesWithCurrencyEffect: new Big(0)
totalValuablesWithCurrencyEffect: new Big(0)
}; };
} }
@ -198,7 +197,6 @@ export abstract class PortfolioCalculator {
let firstTransactionPoint: TransactionPoint = null; let firstTransactionPoint: TransactionPoint = null;
let totalInterestWithCurrencyEffect = new Big(0); let totalInterestWithCurrencyEffect = new Big(0);
let totalLiabilitiesWithCurrencyEffect = new Big(0); let totalLiabilitiesWithCurrencyEffect = new Big(0);
let totalValuablesWithCurrencyEffect = new Big(0);
for (const { currency, dataSource, symbol } of transactionPoints[ for (const { currency, dataSource, symbol } of transactionPoints[
firstIndex - 1 firstIndex - 1
@ -364,8 +362,7 @@ export abstract class PortfolioCalculator {
totalInterestInBaseCurrency, totalInterestInBaseCurrency,
totalInvestment, totalInvestment,
totalInvestmentWithCurrencyEffect, totalInvestmentWithCurrencyEffect,
totalLiabilitiesInBaseCurrency, totalLiabilitiesInBaseCurrency
totalValuablesInBaseCurrency
} = this.getSymbolMetrics({ } = this.getSymbolMetrics({
chartDateMap, chartDateMap,
marketSymbolMap, marketSymbolMap,
@ -444,10 +441,6 @@ export abstract class PortfolioCalculator {
totalLiabilitiesWithCurrencyEffect = totalLiabilitiesWithCurrencyEffect =
totalLiabilitiesWithCurrencyEffect.plus(totalLiabilitiesInBaseCurrency); totalLiabilitiesWithCurrencyEffect.plus(totalLiabilitiesInBaseCurrency);
totalValuablesWithCurrencyEffect = totalValuablesWithCurrencyEffect.plus(
totalValuablesInBaseCurrency
);
if ( if (
(hasErrors || (hasErrors ||
currentRateErrors.find(({ dataSource, symbol }) => { currentRateErrors.find(({ dataSource, symbol }) => {
@ -597,7 +590,6 @@ export abstract class PortfolioCalculator {
netPerformance: totalNetPerformanceValue.toNumber(), netPerformance: totalNetPerformanceValue.toNumber(),
netPerformanceWithCurrencyEffect: netPerformanceWithCurrencyEffect:
totalNetPerformanceValueWithCurrencyEffect.toNumber(), totalNetPerformanceValueWithCurrencyEffect.toNumber(),
// TODO: Add valuables
netWorth: totalCurrentValueWithCurrencyEffect netWorth: totalCurrentValueWithCurrencyEffect
.plus(totalAccountBalanceWithCurrencyEffect) .plus(totalAccountBalanceWithCurrencyEffect)
.toNumber(), .toNumber(),
@ -619,7 +611,6 @@ export abstract class PortfolioCalculator {
positions, positions,
totalInterestWithCurrencyEffect, totalInterestWithCurrencyEffect,
totalLiabilitiesWithCurrencyEffect, totalLiabilitiesWithCurrencyEffect,
totalValuablesWithCurrencyEffect,
hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors
}; };
} }
@ -754,7 +745,7 @@ export abstract class PortfolioCalculator {
? 0 ? 0
: netPerformanceWithCurrencyEffectSinceStartDate / : netPerformanceWithCurrencyEffectSinceStartDate /
timeWeightedInvestmentValue timeWeightedInvestmentValue
// TODO: Add net worth with valuables // TODO: Add net worth
// netWorth: totalCurrentValueWithCurrencyEffect // netWorth: totalCurrentValueWithCurrencyEffect
// .plus(totalAccountBalanceWithCurrencyEffect) // .plus(totalAccountBalanceWithCurrencyEffect)
// .toNumber() // .toNumber()
@ -819,12 +810,6 @@ export abstract class PortfolioCalculator {
return this.transactionPoints; return this.transactionPoints;
} }
public async getValuablesInBaseCurrency() {
await this.snapshotPromise;
return this.snapshot.totalValuablesWithCurrencyEffect;
}
private getChartDateMap({ private getChartDateMap({
endDate, endDate,
startDate, startDate,
@ -1000,19 +985,12 @@ export abstract class PortfolioCalculator {
liabilities = quantity.mul(unitPrice); liabilities = quantity.mul(unitPrice);
} }
let valuables = new Big(0);
if (type === 'ITEM') {
valuables = quantity.mul(unitPrice);
}
if (lastDate !== date || lastTransactionPoint === null) { if (lastDate !== date || lastTransactionPoint === null) {
lastTransactionPoint = { lastTransactionPoint = {
date, date,
fees, fees,
interest, interest,
liabilities, liabilities,
valuables,
items: newItems items: newItems
}; };
@ -1024,8 +1002,6 @@ export abstract class PortfolioCalculator {
lastTransactionPoint.items = newItems; lastTransactionPoint.items = newItems;
lastTransactionPoint.liabilities = lastTransactionPoint.liabilities =
lastTransactionPoint.liabilities.plus(liabilities); lastTransactionPoint.liabilities.plus(liabilities);
lastTransactionPoint.valuables =
lastTransactionPoint.valuables.plus(valuables);
} }
lastDate = date; lastDate = date;

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts

@ -194,8 +194,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts

@ -179,8 +179,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts

@ -170,8 +170,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('273.2'), totalInvestment: new Big('273.2'),
totalInvestmentWithCurrencyEffect: new Big('273.2'), totalInvestmentWithCurrencyEffect: new Big('273.2'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts

@ -224,8 +224,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('44558.42'), totalInvestment: new Big('44558.42'),
totalInvestmentWithCurrencyEffect: new Big('44558.42'), totalInvestmentWithCurrencyEffect: new Big('44558.42'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(investments).toEqual([ expect(investments).toEqual([

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts

@ -198,8 +198,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('320.43').mul(0.97373), totalInvestment: new Big('320.43').mul(0.97373),
totalInvestmentWithCurrencyEffect: new Big('318.542667299999967957'), totalInvestmentWithCurrencyEffect: new Big('318.542667299999967957'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts

@ -224,8 +224,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('44558.42'), totalInvestment: new Big('44558.42'),
totalInvestmentWithCurrencyEffect: new Big('44558.42'), totalInvestmentWithCurrencyEffect: new Big('44558.42'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(investments).toEqual([ expect(investments).toEqual([

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts

@ -151,8 +151,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts

@ -177,8 +177,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('89.12').mul(0.8854), totalInvestment: new Big('89.12').mul(0.8854),
totalInvestmentWithCurrencyEffect: new Big('82.329056'), totalInvestmentWithCurrencyEffect: new Big('82.329056'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts

@ -170,8 +170,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('298.58'), totalInvestment: new Big('298.58'),
totalInvestmentWithCurrencyEffect: new Big('298.58'), totalInvestmentWithCurrencyEffect: new Big('298.58'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts

@ -105,8 +105,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(investments).toEqual([]); expect(investments).toEqual([]);

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts

@ -177,8 +177,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('75.80'), totalInvestment: new Big('75.80'),
totalInvestmentWithCurrencyEffect: new Big('75.80'), totalInvestmentWithCurrencyEffect: new Big('75.80'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts

@ -228,8 +228,7 @@ describe('PortfolioCalculator', () => {
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'),
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(

33
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts → apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-valuable.spec.ts

@ -82,7 +82,7 @@ describe('PortfolioCalculator', () => {
}); });
describe('compute portfolio snapshot', () => { describe('compute portfolio snapshot', () => {
it.only('with item activity', async () => { it.only('with valuable activity', async () => {
jest.useFakeTimers().setSystemTime(parseDate('2022-01-31').getTime()); jest.useFakeTimers().setSystemTime(parseDate('2022-01-31').getTime());
const activities: Activity[] = [ const activities: Activity[] = [
@ -98,7 +98,7 @@ describe('PortfolioCalculator', () => {
name: 'Penthouse Apartment', name: 'Penthouse Apartment',
symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde' symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde'
}, },
type: 'ITEM', type: 'BUY',
unitPriceInAssetProfileCurrency: 500000 unitPriceInAssetProfileCurrency: 500000
} }
]; ];
@ -113,9 +113,15 @@ describe('PortfolioCalculator', () => {
const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); const portfolioSnapshot = await portfolioCalculator.computeSnapshot();
expect(portfolioSnapshot).toMatchObject({ expect(portfolioSnapshot).toMatchObject({
currentValueInBaseCurrency: new Big('0'), currentValueInBaseCurrency: new Big('500000'),
errors: [], // TODO: []
hasErrors: true, errors: [
{
dataSource: 'MANUAL',
symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde'
}
],
hasErrors: true, // TODO: false
positions: [ positions: [
{ {
averagePrice: new Big('500000'), averagePrice: new Big('500000'),
@ -130,29 +136,28 @@ describe('PortfolioCalculator', () => {
grossPerformancePercentage: null, grossPerformancePercentage: null,
grossPerformancePercentageWithCurrencyEffect: null, grossPerformancePercentageWithCurrencyEffect: null,
grossPerformanceWithCurrencyEffect: null, grossPerformanceWithCurrencyEffect: null,
investment: new Big('0'), investment: new Big('0'), // TODO: new Big('500000')
investmentWithCurrencyEffect: new Big('0'), investmentWithCurrencyEffect: new Big('0'), // TODO: new Big('500000')
marketPrice: null, marketPrice: null,
marketPriceInBaseCurrency: 500000, marketPriceInBaseCurrency: 500000,
netPerformance: null, netPerformance: null,
netPerformancePercentage: null, netPerformancePercentage: null,
netPerformancePercentageWithCurrencyEffectMap: null, netPerformancePercentageWithCurrencyEffectMap: null,
netPerformanceWithCurrencyEffectMap: null, netPerformanceWithCurrencyEffectMap: null,
quantity: new Big('0'), quantity: new Big('1'),
symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde', symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde',
tags: [], tags: [],
timeWeightedInvestment: new Big('0'), timeWeightedInvestment: new Big('0'),
timeWeightedInvestmentWithCurrencyEffect: new Big('0'), timeWeightedInvestmentWithCurrencyEffect: new Big('0'),
transactionCount: 1, transactionCount: 1,
valueInBaseCurrency: new Big('0') valueInBaseCurrency: new Big('500000')
} }
], ],
totalFeesWithCurrencyEffect: new Big('0'), totalFeesWithCurrencyEffect: new Big('0'),
totalInterestWithCurrencyEffect: new Big('0'), totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'), // TODO: new Big('500000')
totalInvestmentWithCurrencyEffect: new Big('0'), totalInvestmentWithCurrencyEffect: new Big('0'), // TODO: new Big('500000')
totalLiabilitiesWithCurrencyEffect: new Big('0'), totalLiabilitiesWithCurrencyEffect: new Big('0')
totalValuablesWithCurrencyEffect: new Big('0')
}); });
expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject(
@ -161,7 +166,7 @@ describe('PortfolioCalculator', () => {
netPerformanceInPercentage: 0, netPerformanceInPercentage: 0,
netPerformanceInPercentageWithCurrencyEffect: 0, netPerformanceInPercentageWithCurrencyEffect: 0,
netPerformanceWithCurrencyEffect: 0, netPerformanceWithCurrencyEffect: 0,
totalInvestmentValueWithCurrencyEffect: 0 totalInvestmentValueWithCurrencyEffect: 0 // TODO: 500000
}) })
); );
}); });

22
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts

@ -108,8 +108,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
createdAt: new Date(), createdAt: new Date(),
errors: [], errors: [],
historicalData: [], historicalData: [],
totalLiabilitiesWithCurrencyEffect: new Big(0), totalLiabilitiesWithCurrencyEffect: new Big(0)
totalValuablesWithCurrencyEffect: new Big(0)
}; };
} }
@ -179,8 +178,6 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
let totalLiabilitiesInBaseCurrency = new Big(0); let totalLiabilitiesInBaseCurrency = new Big(0);
let totalQuantityFromBuyTransactions = new Big(0); let totalQuantityFromBuyTransactions = new Big(0);
let totalUnits = new Big(0); let totalUnits = new Big(0);
let totalValuables = new Big(0);
let totalValuablesInBaseCurrency = new Big(0);
let valueAtStartDate: Big; let valueAtStartDate: Big;
let valueAtStartDateWithCurrencyEffect: Big; let valueAtStartDateWithCurrencyEffect: Big;
@ -224,9 +221,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0),
totalLiabilities: new Big(0), totalLiabilities: new Big(0),
totalLiabilitiesInBaseCurrency: new Big(0), totalLiabilitiesInBaseCurrency: new Big(0)
totalValuables: new Big(0),
totalValuablesInBaseCurrency: new Big(0)
}; };
} }
@ -274,9 +269,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0), totalInvestmentWithCurrencyEffect: new Big(0),
totalLiabilities: new Big(0), totalLiabilities: new Big(0),
totalLiabilitiesInBaseCurrency: new Big(0), totalLiabilitiesInBaseCurrency: new Big(0)
totalValuables: new Big(0),
totalValuablesInBaseCurrency: new Big(0)
}; };
} }
@ -412,13 +405,6 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus( totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus(
interest.mul(exchangeRateAtOrderDate ?? 1) interest.mul(exchangeRateAtOrderDate ?? 1)
); );
} else if (order.type === 'ITEM') {
const valuables = order.quantity.mul(order.unitPrice);
totalValuables = totalValuables.plus(valuables);
totalValuablesInBaseCurrency = totalValuablesInBaseCurrency.plus(
valuables.mul(exchangeRateAtOrderDate ?? 1)
);
} else if (order.type === 'LIABILITY') { } else if (order.type === 'LIABILITY') {
const liabilities = order.quantity.mul(order.unitPrice); const liabilities = order.quantity.mul(order.unitPrice);
@ -971,8 +957,6 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
totalInvestmentWithCurrencyEffect, totalInvestmentWithCurrencyEffect,
totalLiabilities, totalLiabilities,
totalLiabilitiesInBaseCurrency, totalLiabilitiesInBaseCurrency,
totalValuables,
totalValuablesInBaseCurrency,
grossPerformance: totalGrossPerformance, grossPerformance: totalGrossPerformance,
grossPerformanceWithCurrencyEffect: grossPerformanceWithCurrencyEffect:
totalGrossPerformanceWithCurrencyEffect, totalGrossPerformanceWithCurrencyEffect,

1
apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts

@ -8,5 +8,4 @@ export interface TransactionPoint {
interest: Big; interest: Big;
items: TransactionPointSymbol[]; items: TransactionPointSymbol[];
liabilities: Big; liabilities: Big;
valuables: Big;
} }

4
apps/api/src/app/portfolio/portfolio.service.ts

@ -1825,8 +1825,6 @@ export class PortfolioService {
const liabilities = const liabilities =
await portfolioCalculator.getLiabilitiesInBaseCurrency(); await portfolioCalculator.getLiabilitiesInBaseCurrency();
const valuables = await portfolioCalculator.getValuablesInBaseCurrency();
const totalBuy = this.getSumOfActivityType({ const totalBuy = this.getSumOfActivityType({
userCurrency, userCurrency,
activities: nonExcludedActivities, activities: nonExcludedActivities,
@ -1875,7 +1873,6 @@ export class PortfolioService {
const netWorth = new Big(balanceInBaseCurrency) const netWorth = new Big(balanceInBaseCurrency)
.plus(currentValueInBaseCurrency) .plus(currentValueInBaseCurrency)
.plus(valuables)
.plus(excludedAccountsAndActivities) .plus(excludedAccountsAndActivities)
.minus(liabilities) .minus(liabilities)
.toNumber(); .toNumber();
@ -1934,7 +1931,6 @@ export class PortfolioService {
.plus(fees) .plus(fees)
.toNumber(), .toNumber(),
interest: interest.toNumber(), interest: interest.toNumber(),
items: valuables.toNumber(),
liabilities: liabilities.toNumber(), liabilities: liabilities.toNumber(),
totalInvestment: totalInvestment.toNumber(), totalInvestment: totalInvestment.toNumber(),
totalValueInBaseCurrency: netWorth totalValueInBaseCurrency: netWorth

12
apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html

@ -152,18 +152,6 @@
/> />
</div> </div>
</div> </div>
<div class="flex-nowrap px-3 py-1 row">
<div class="flex-grow-1 text-truncate" i18n>Valuables</div>
<div class="justify-content-end">
<gf-value
class="justify-content-end"
[isCurrency]="true"
[locale]="locale"
[unit]="baseCurrency"
[value]="isLoading ? undefined : summary?.items"
/>
</div>
</div>
<div class="flex-nowrap px-3 py-1 row"> <div class="flex-nowrap px-3 py-1 row">
<div class="flex-grow-1 text-truncate" i18n>Emergency Fund</div> <div class="flex-grow-1 text-truncate" i18n>Emergency Fund</div>
<div <div

29
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts

@ -194,9 +194,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
) )
.subscribe(async () => { .subscribe(async () => {
if ( if (
this.activityForm.get('type').value === 'BUY' || ['BUY', 'FEE', 'ITEM'].includes(this.activityForm.get('type').value)
this.activityForm.get('type').value === 'FEE' ||
this.activityForm.get('type').value === 'ITEM'
) { ) {
this.total = this.total =
this.activityForm.get('quantity').value * this.activityForm.get('quantity').value *
@ -215,12 +213,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
this.activityForm.get('accountId').valueChanges.subscribe((accountId) => { this.activityForm.get('accountId').valueChanges.subscribe((accountId) => {
const type = this.activityForm.get('type').value; const type = this.activityForm.get('type').value;
if ( if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(type)) {
type === 'FEE' ||
type === 'INTEREST' ||
type === 'ITEM' ||
type === 'LIABILITY'
) {
const currency = const currency =
this.data.accounts.find(({ id }) => { this.data.accounts.find(({ id }) => {
return id === accountId; return id === accountId;
@ -297,7 +290,11 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
.get('type') .get('type')
.valueChanges.pipe(takeUntil(this.unsubscribeSubject)) .valueChanges.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((type: Type) => { .subscribe((type: Type) => {
if (type === 'ITEM') { if (
type === 'ITEM' ||
(this.activityForm.get('dataSource').value === 'MANUAL' &&
type === 'BUY')
) {
this.activityForm this.activityForm
.get('accountId') .get('accountId')
.removeValidators(Validators.required); .removeValidators(Validators.required);
@ -472,6 +469,12 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
object: activity object: activity
}); });
if (activity.type === 'ITEM') {
// Transform deprecated type ITEM
activity.dataSource = 'MANUAL';
activity.type = 'BUY';
}
this.dialogRef.close(activity); this.dialogRef.close(activity);
} else { } else {
(activity as UpdateOrderDto).id = this.data.activity?.id; (activity as UpdateOrderDto).id = this.data.activity?.id;
@ -483,6 +486,12 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
object: activity as UpdateOrderDto object: activity as UpdateOrderDto
}); });
if (activity.type === 'ITEM') {
// Transform deprecated type ITEM
activity.dataSource = 'MANUAL';
activity.type = 'BUY';
}
this.dialogRef.close(activity as UpdateOrderDto); this.dialogRef.close(activity as UpdateOrderDto);
} }
} catch (error) { } catch (error) {

2
apps/client/src/app/services/import-activities.service.ts

@ -343,8 +343,6 @@ export class ImportActivitiesService {
return 'FEE'; return 'FEE';
case 'interest': case 'interest':
return 'INTEREST'; return 'INTEREST';
case 'item':
return 'ITEM';
case 'liability': case 'liability':
return 'LIABILITY'; return 'LIABILITY';
case 'sell': case 'sell':

1
libs/common/src/lib/interfaces/portfolio-summary.interface.ts

@ -20,7 +20,6 @@ export interface PortfolioSummary extends PortfolioPerformance {
grossPerformance: number; grossPerformance: number;
grossPerformanceWithCurrencyEffect: number; grossPerformanceWithCurrencyEffect: number;
interest: number; interest: number;
items: number;
liabilities: number; liabilities: number;
totalBuy: number; totalBuy: number;
totalSell: number; totalSell: number;

2
libs/common/src/lib/interfaces/symbol-metrics.interface.ts

@ -51,6 +51,4 @@ export interface SymbolMetrics {
totalInvestmentWithCurrencyEffect: Big; totalInvestmentWithCurrencyEffect: Big;
totalLiabilities: Big; totalLiabilities: Big;
totalLiabilitiesInBaseCurrency: Big; totalLiabilitiesInBaseCurrency: Big;
totalValuables: Big;
totalValuablesInBaseCurrency: Big;
} }

4
libs/common/src/lib/models/portfolio-snapshot.ts

@ -45,8 +45,4 @@ export class PortfolioSnapshot {
@Transform(transformToBig, { toClassOnly: true }) @Transform(transformToBig, { toClassOnly: true })
@Type(() => Big) @Type(() => Big)
totalLiabilitiesWithCurrencyEffect: Big; totalLiabilitiesWithCurrencyEffect: Big;
@Transform(transformToBig, { toClassOnly: true })
@Type(() => Big)
totalValuablesWithCurrencyEffect: Big;
} }

3
libs/ui/src/lib/activity-type/activity-type.component.html

@ -5,7 +5,6 @@
dividend: activityType === 'DIVIDEND', dividend: activityType === 'DIVIDEND',
fee: activityType === 'FEE', fee: activityType === 'FEE',
interest: activityType === 'INTEREST', interest: activityType === 'INTEREST',
item: activityType === 'ITEM',
liability: activityType === 'LIABILITY', liability: activityType === 'LIABILITY',
sell: activityType === 'SELL' sell: activityType === 'SELL'
}" }"
@ -16,8 +15,6 @@
<ion-icon name="add-circle-outline" /> <ion-icon name="add-circle-outline" />
} @else if (activityType === 'FEE') { } @else if (activityType === 'FEE') {
<ion-icon name="hammer-outline" /> <ion-icon name="hammer-outline" />
} @else if (activityType === 'ITEM') {
<ion-icon name="cube-outline" />
} @else if (activityType === 'LIABILITY') { } @else if (activityType === 'LIABILITY') {
<ion-icon name="flame-outline" /> <ion-icon name="flame-outline" />
} @else if (activityType === 'SELL') { } @else if (activityType === 'SELL') {

4
libs/ui/src/lib/activity-type/activity-type.component.scss

@ -26,10 +26,6 @@
color: var(--cyan); color: var(--cyan);
} }
&.item {
color: var(--purple);
}
&.liability { &.liability {
color: var(--red); color: var(--red);
} }

2
prisma/migrations/20250704214021_changed_type_from_item_to_buy_in_order/migration.sql

@ -0,0 +1,2 @@
-- AlterTable
UPDATE "Order" SET "type" = 'BUY' WHERE "type" = 'ITEM';

20
test/import/not-ok/invalid-type-deprecated.json

@ -0,0 +1,20 @@
{
"meta": {
"date": "2023-02-05T00:00:00.000Z",
"version": "dev"
},
"activities": [
{
"accountId": null,
"comment": null,
"fee": 0,
"quantity": 1,
"type": "ITEM",
"unitPrice": 500000,
"currency": "USD",
"dataSource": "MANUAL",
"date": "2022-01-01T00:00:00.000Z",
"symbol": "Penthouse Apartment"
}
]
}

2
test/import/ok/sample.csv

@ -2,5 +2,5 @@ Date,Code,DataSource,Currency,Price,Quantity,Action,Fee,Note
01-09-2021,Account Opening Fee,MANUAL,USD,0,0,fee,49, 01-09-2021,Account Opening Fee,MANUAL,USD,0,0,fee,49,
16-09-2021,MSFT,YAHOO,USD,298.580,5,buy,19.00,My first order 🤓 16-09-2021,MSFT,YAHOO,USD,298.580,5,buy,19.00,My first order 🤓
17/11/2021,MSFT,YAHOO,USD,0.62,5,dividend,0.00, 17/11/2021,MSFT,YAHOO,USD,0.62,5,dividend,0.00,
01.01.2022,Penthouse Apartment,MANUAL,USD,500000.0,1,item,0.00, 01.01.2022,Penthouse Apartment,MANUAL,USD,500000.0,1,buy,0.00,
20500606,US5949181045,YAHOO,USD,0.00,0,buy,0.00, 20500606,US5949181045,YAHOO,USD,0.00,0,buy,0.00,

1 Date Code DataSource Currency Price Quantity Action Fee Note
2 01-09-2021 Account Opening Fee MANUAL USD 0 0 fee 49
3 16-09-2021 MSFT YAHOO USD 298.580 5 buy 19.00 My first order 🤓
4 17/11/2021 MSFT YAHOO USD 0.62 5 dividend 0.00
5 01.01.2022 Penthouse Apartment MANUAL USD 500000.0 1 item buy 0.00
6 20500606 US5949181045 YAHOO USD 0.00 0 buy 0.00

2
test/import/ok/sample.json

@ -41,7 +41,7 @@
"comment": null, "comment": null,
"fee": 0, "fee": 0,
"quantity": 1, "quantity": 1,
"type": "ITEM", "type": "BUY",
"unitPrice": 500000, "unitPrice": 500000,
"currency": "USD", "currency": "USD",
"dataSource": "MANUAL", "dataSource": "MANUAL",

2
test/import/ok/without-accounts.json

@ -17,7 +17,7 @@
{ {
"fee": 0, "fee": 0,
"quantity": 1, "quantity": 1,
"type": "ITEM", "type": "BUY",
"unitPrice": 500000, "unitPrice": 500000,
"currency": "USD", "currency": "USD",
"dataSource": "MANUAL", "dataSource": "MANUAL",

Loading…
Cancel
Save