Browse Source

Deprecate ITEM activity type in favor of BUY

pull/5093/head
Thomas Kaul 2 months ago
parent
commit
4d01185af1
  1. 25
      README.md
  2. 8
      apps/api/src/app/export/export.service.ts
  3. 2
      apps/api/src/app/import/import.service.ts
  4. 10
      apps/api/src/app/order/order.service.ts
  5. 23
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-valuable.spec.ts
  6. 2
      apps/client/src/app/services/import-activities.service.ts
  7. 3
      libs/ui/src/lib/activity-type/activity-type.component.html
  8. 4
      libs/ui/src/lib/activity-type/activity-type.component.scss
  9. 1
      libs/ui/src/lib/i18n.ts

25
README.md

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

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

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

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

@ -232,7 +232,7 @@ export class ImportService {
for (const activity of activitiesDto) {
if (!activity.dataSource) {
if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(activity.type)) {
if (['FEE', 'INTEREST', 'LIABILITY'].includes(activity.type)) {
activity.dataSource = DataSource.MANUAL;
} else {
activity.dataSource =

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

@ -118,7 +118,7 @@ export class OrderService {
const userId = data.userId;
if (
['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type) ||
['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) ||
(data.SymbolProfile.connectOrCreate.create.dataSource === 'MANUAL' &&
data.type === 'BUY')
) {
@ -174,7 +174,7 @@ export class OrderService {
const orderData: Prisma.OrderCreateInput = data;
const isDraft = ['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type)
const isDraft = ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type)
? false
: isAfter(data.date as Date, endOfToday());
@ -647,7 +647,11 @@ export class OrderService {
let isDraft = false;
if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type)) {
if (
['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) ||
(data.SymbolProfile.connect.dataSource_symbol.dataSource === 'MANUAL' &&
data.type === 'BUY')
) {
delete data.SymbolProfile.connect;
if (data.account?.connect?.id_userId?.id === null) {

23
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', () => {
it.only('with item activity', async () => {
it.only('with valuable activity', async () => {
jest.useFakeTimers().setSystemTime(parseDate('2022-01-31').getTime());
const activities: Activity[] = [
@ -98,7 +98,7 @@ describe('PortfolioCalculator', () => {
name: 'Penthouse Apartment',
symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde'
},
type: 'ITEM',
type: 'BUY',
unitPriceInAssetProfileCurrency: 500000
}
];
@ -113,8 +113,15 @@ describe('PortfolioCalculator', () => {
const portfolioSnapshot = await portfolioCalculator.computeSnapshot();
expect(portfolioSnapshot).toMatchObject({
currentValueInBaseCurrency: new Big('0'),
errors: [],
currentValueInBaseCurrency: new Big('500000'),
// TODO
errors: [
{
dataSource: 'MANUAL',
symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde'
}
],
// TODO
hasErrors: true,
positions: [
{
@ -130,21 +137,21 @@ describe('PortfolioCalculator', () => {
grossPerformancePercentage: null,
grossPerformancePercentageWithCurrencyEffect: null,
grossPerformanceWithCurrencyEffect: null,
investment: new Big('0'),
investmentWithCurrencyEffect: new Big('0'),
investment: new Big('0'), // TODO
investmentWithCurrencyEffect: new Big('0'), // TODO
marketPrice: null,
marketPriceInBaseCurrency: 500000,
netPerformance: null,
netPerformancePercentage: null,
netPerformancePercentageWithCurrencyEffectMap: null,
netPerformanceWithCurrencyEffectMap: null,
quantity: new Big('0'),
quantity: new Big('1'),
symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde',
tags: [],
timeWeightedInvestment: new Big('0'),
timeWeightedInvestmentWithCurrencyEffect: new Big('0'),
transactionCount: 1,
valueInBaseCurrency: new Big('0')
valueInBaseCurrency: new Big('500000')
}
],
totalFeesWithCurrencyEffect: new Big('0'),

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

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

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

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

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

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

1
libs/ui/src/lib/i18n.ts

@ -36,7 +36,6 @@ const locales = {
DIVIDEND: $localize`Dividend`,
FEE: $localize`Fee`,
INTEREST: $localize`Interest`,
ITEM: $localize`Valuable`,
LIABILITY: $localize`Liability`,
SELL: $localize`Sell`,

Loading…
Cancel
Save