Browse Source

Merge branch 'main' into feature/store-activitiescount-in-portfoliosnapshot

pull/4352/head
Thomas Kaul 2 months ago
committed by GitHub
parent
commit
2ea1cb1307
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      CHANGELOG.md
  2. 3
      apps/api/src/app/export/export.module.ts
  3. 28
      apps/api/src/app/export/export.service.ts
  4. 9
      apps/api/src/app/user/user.service.ts
  5. 11
      libs/common/src/lib/interfaces/export.interface.ts
  6. 1
      libs/common/src/lib/interfaces/user.interface.ts
  7. 4
      libs/ui/src/lib/value/value.component.html
  8. 8
      package-lock.json
  9. 2
      package.json

12
CHANGELOG.md

@ -9,7 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Added the activities count to the portfolio snapshot in the portfolio calculator - Extended the export functionality by the tags
- Extended the portfolio snapshot in the portfolio calculator by the activities count
- Extended the user endpoint `GET api/v1/user` by the activities count
### Changed
- Upgraded `prettier` from version `3.4.2` to `3.5.1`
### Fixed
- Improved the numeric comparison of strings in the value component
## 2.140.0 - 2025-02-20 ## 2.140.0 - 2025-02-20

3
apps/api/src/app/export/export.module.ts

@ -1,6 +1,7 @@
import { AccountModule } from '@ghostfolio/api/app/account/account.module'; import { AccountModule } from '@ghostfolio/api/app/account/account.module';
import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { OrderModule } from '@ghostfolio/api/app/order/order.module';
import { ApiModule } from '@ghostfolio/api/services/api/api.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module';
import { TagModule } from '@ghostfolio/api/services/tag/tag.module';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
@ -8,7 +9,7 @@ import { ExportController } from './export.controller';
import { ExportService } from './export.service'; import { ExportService } from './export.service';
@Module({ @Module({
imports: [AccountModule, ApiModule, OrderModule], imports: [AccountModule, ApiModule, OrderModule, TagModule],
controllers: [ExportController], controllers: [ExportController],
providers: [ExportService] providers: [ExportService]
}) })

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

@ -1,6 +1,7 @@
import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service';
import { OrderService } from '@ghostfolio/api/app/order/order.service'; import { OrderService } from '@ghostfolio/api/app/order/order.service';
import { environment } from '@ghostfolio/api/environments/environment'; import { environment } from '@ghostfolio/api/environments/environment';
import { TagService } from '@ghostfolio/api/services/tag/tag.service';
import { Filter, Export } from '@ghostfolio/common/interfaces'; import { Filter, Export } from '@ghostfolio/common/interfaces';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
@ -9,7 +10,8 @@ import { Injectable } from '@nestjs/common';
export class ExportService { export class ExportService {
public constructor( public constructor(
private readonly accountService: AccountService, private readonly accountService: AccountService,
private readonly orderService: OrderService private readonly orderService: OrderService,
private readonly tagService: TagService
) {} ) {}
public async export({ public async export({
@ -60,9 +62,21 @@ export class ExportService {
}); });
} }
const tags = (await this.tagService.getTagsForUser(userId))
.filter(({ isUsed }) => {
return isUsed;
})
.map(({ id, name }) => {
return {
id,
name
};
});
return { return {
meta: { date: new Date().toISOString(), version: environment.version }, meta: { date: new Date().toISOString(), version: environment.version },
accounts, accounts,
tags,
activities: activities.map( activities: activities.map(
({ ({
accountId, accountId,
@ -72,6 +86,7 @@ export class ExportService {
id, id,
quantity, quantity,
SymbolProfile, SymbolProfile,
tags: currentTags,
type, type,
unitPrice unitPrice
}) => { }) => {
@ -86,13 +101,12 @@ export class ExportService {
currency: SymbolProfile.currency, currency: SymbolProfile.currency,
dataSource: SymbolProfile.dataSource, dataSource: SymbolProfile.dataSource,
date: date.toISOString(), date: date.toISOString(),
symbol: symbol: ['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(type)
type === 'FEE' ||
type === 'INTEREST' ||
type === 'ITEM' ||
type === 'LIABILITY'
? SymbolProfile.name ? SymbolProfile.name
: SymbolProfile.symbol : SymbolProfile.symbol,
tags: currentTags.map(({ id: tagId }) => {
return tagId;
})
}; };
} }
), ),

9
apps/api/src/app/user/user.service.ts

@ -86,6 +86,9 @@ export class UserService {
orderBy: { alias: 'asc' }, orderBy: { alias: 'asc' },
where: { GranteeUser: { id } } where: { GranteeUser: { id } }
}), }),
this.prismaService.order.count({
where: { userId: id }
}),
this.prismaService.order.findFirst({ this.prismaService.order.findFirst({
orderBy: { orderBy: {
date: 'asc' date: 'asc'
@ -96,8 +99,9 @@ export class UserService {
]); ]);
const access = userData[0]; const access = userData[0];
const firstActivity = userData[1]; const activitiesCount = userData[1];
let tags = userData[2]; const firstActivity = userData[2];
let tags = userData[3];
let systemMessage: SystemMessage; let systemMessage: SystemMessage;
@ -117,6 +121,7 @@ export class UserService {
} }
return { return {
activitiesCount,
id, id,
permissions, permissions,
subscription, subscription,

11
libs/common/src/lib/interfaces/export.interface.ts

@ -1,10 +1,6 @@
import { Account, Order } from '@prisma/client'; import { Account, Order, Tag } from '@prisma/client';
export interface Export { export interface Export {
meta: {
date: string;
version: string;
};
accounts: Omit<Account, 'createdAt' | 'updatedAt' | 'userId'>[]; accounts: Omit<Account, 'createdAt' | 'updatedAt' | 'userId'>[];
activities: (Omit< activities: (Omit<
Order, Order,
@ -16,5 +12,10 @@ export interface Export {
| 'updatedAt' | 'updatedAt'
| 'userId' | 'userId'
> & { date: string; symbol: string })[]; > & { date: string; symbol: string })[];
meta: {
date: string;
version: string;
};
tags: Omit<Tag, 'userId'>[];
user: { settings: { currency: string } }; user: { settings: { currency: string } };
} }

1
libs/common/src/lib/interfaces/user.interface.ts

@ -10,6 +10,7 @@ import { UserSettings } from './user-settings.interface';
export interface User { export interface User {
access: Pick<Access, 'alias' | 'id' | 'permissions'>[]; access: Pick<Access, 'alias' | 'id' | 'permissions'>[];
accounts: Account[]; accounts: Account[];
activitiesCount: number;
dateOfFirstActivity: Date; dateOfFirstActivity: Date;
id: string; id: string;
permissions: string[]; permissions: string[];

4
libs/ui/src/lib/value/value.component.html

@ -10,8 +10,8 @@
> >
<ng-container *ngIf="isNumber || value === null"> <ng-container *ngIf="isNumber || value === null">
<ng-container *ngIf="colorizeSign && !useAbsoluteValue"> <ng-container *ngIf="colorizeSign && !useAbsoluteValue">
<div *ngIf="value > 0" class="mr-1 text-success">+</div> <div *ngIf="+value > 0" class="mr-1 text-success">+</div>
<div *ngIf="value < 0" class="mr-1 text-danger">-</div> <div *ngIf="+value < 0" class="mr-1 text-danger">-</div>
</ng-container> </ng-container>
<div <div
*ngIf="isPercent" *ngIf="isPercent"

8
package-lock.json

@ -149,7 +149,7 @@
"jest-environment-jsdom": "29.7.0", "jest-environment-jsdom": "29.7.0",
"jest-preset-angular": "14.4.2", "jest-preset-angular": "14.4.2",
"nx": "20.3.2", "nx": "20.3.2",
"prettier": "3.4.2", "prettier": "3.5.1",
"prettier-plugin-organize-attributes": "1.0.0", "prettier-plugin-organize-attributes": "1.0.0",
"prisma": "6.3.0", "prisma": "6.3.0",
"react": "18.2.0", "react": "18.2.0",
@ -27104,9 +27104,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "3.4.2", "version": "3.5.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.1.tgz",
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "integrity": "sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {

2
package.json

@ -195,7 +195,7 @@
"jest-environment-jsdom": "29.7.0", "jest-environment-jsdom": "29.7.0",
"jest-preset-angular": "14.4.2", "jest-preset-angular": "14.4.2",
"nx": "20.3.2", "nx": "20.3.2",
"prettier": "3.4.2", "prettier": "3.5.1",
"prettier-plugin-organize-attributes": "1.0.0", "prettier-plugin-organize-attributes": "1.0.0",
"prisma": "6.3.0", "prisma": "6.3.0",
"react": "18.2.0", "react": "18.2.0",

Loading…
Cancel
Save