Browse Source

Merge remote-tracking branch 'origin/main' into feature/extend-watchlist-endpoint

pull/4634/head
KenTandrian 4 months ago
parent
commit
6c719811de
  1. 7
      CHANGELOG.md
  2. 6
      apps/api/src/app/account/account.controller.ts
  3. 14
      apps/api/src/app/account/account.service.ts
  4. 2
      apps/api/src/app/order/order.service.ts
  5. 10
      apps/api/src/app/portfolio/portfolio.service.ts
  6. 18
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  7. 4
      package-lock.json
  8. 2
      package.json
  9. 2
      prisma/schema.prisma

7
CHANGELOG.md

@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
## 2.158.0 - 2025-04-30
### Added
@ -13,8 +13,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Renamed `Order` to `activities` in the `Account` database schema
- Improved the language localization for German (`de`)
### Fixed
- Fixed an issue with the saving of activities with type `INTEREST`, `ITEM` and `LIABILITY`
## 2.157.1 - 2025-04-29
### Added

6
apps/api/src/app/account/account.controller.ts

@ -57,17 +57,17 @@ export class AccountController {
@HasPermission(permissions.deleteAccount)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async deleteAccount(@Param('id') id: string): Promise<AccountModel> {
const account = await this.accountService.accountWithOrders(
const account = await this.accountService.accountWithActivities(
{
id_userId: {
id,
userId: this.request.user.id
}
},
{ Order: true }
{ activities: true }
);
if (!account || account?.Order.length > 0) {
if (!account || account?.activities.length > 0) {
throw new HttpException(
getReasonPhrase(StatusCodes.FORBIDDEN),
StatusCodes.FORBIDDEN

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

@ -39,12 +39,12 @@ export class AccountService {
return account;
}
public async accountWithOrders(
public async accountWithActivities(
accountWhereUniqueInput: Prisma.AccountWhereUniqueInput,
accountInclude: Prisma.AccountInclude
): Promise<
Account & {
Order?: Order[];
activities?: Order[];
}
> {
return this.prismaService.account.findUnique({
@ -62,8 +62,8 @@ export class AccountService {
orderBy?: Prisma.AccountOrderByWithRelationInput;
}): Promise<
(Account & {
activities?: Order[];
balances?: AccountBalance[];
Order?: Order[];
Platform?: Platform;
})[]
> {
@ -140,7 +140,7 @@ export class AccountService {
public async getAccounts(aUserId: string): Promise<Account[]> {
const accounts = await this.accounts({
include: { Order: true, Platform: true },
include: { activities: true, Platform: true },
orderBy: { name: 'asc' },
where: { userId: aUserId }
});
@ -148,15 +148,15 @@ export class AccountService {
return accounts.map((account) => {
let transactionCount = 0;
for (const order of account.Order) {
if (!order.isDraft) {
for (const { isDraft } of account.activities) {
if (!isDraft) {
transactionCount += 1;
}
}
const result = { ...account, transactionCount };
delete result.Order;
delete result.activities;
return result;
});

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

@ -100,7 +100,7 @@ export class OrderService {
userId: string;
}
): Promise<Order> {
let Account: Prisma.AccountCreateNestedOneWithoutOrderInput;
let Account: Prisma.AccountCreateNestedOneWithoutActivitiesInput;
if (data.accountId) {
Account = {

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

@ -139,7 +139,7 @@ export class PortfolioService {
}
if (filterByDataSource && filterBySymbol) {
where.Order = {
where.activities = {
some: {
SymbolProfile: {
AND: [
@ -154,7 +154,7 @@ export class PortfolioService {
const [accounts, details] = await Promise.all([
this.accountService.accounts({
where,
include: { Order: true, Platform: true },
include: { activities: true, Platform: true },
orderBy: { name: 'asc' }
}),
this.getDetails({
@ -170,8 +170,8 @@ export class PortfolioService {
return accounts.map((account) => {
let transactionCount = 0;
for (const order of account.Order) {
if (!order.isDraft) {
for (const { isDraft } of account.activities) {
if (!isDraft) {
transactionCount += 1;
}
}
@ -195,7 +195,7 @@ export class PortfolioService {
)
};
delete result.Order;
delete result.activities;
return result;
});

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

@ -238,7 +238,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
.get('dataSource')
.removeValidators(Validators.required);
this.activityForm.get('dataSource').updateValueAndValidity();
this.activityForm.get('fee').reset();
this.activityForm.get('fee').setValue(0);
this.activityForm.get('name').setValidators(Validators.required);
this.activityForm.get('name').updateValueAndValidity();
this.activityForm.get('quantity').setValue(1);
@ -248,11 +248,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
this.activityForm.get('searchSymbol').updateValueAndValidity();
this.activityForm.get('updateAccountBalance').disable();
this.activityForm.get('updateAccountBalance').setValue(false);
} else if (
type === 'FEE' ||
type === 'INTEREST' ||
type === 'LIABILITY'
) {
} else if (['FEE', 'INTEREST', 'LIABILITY'].includes(type)) {
this.activityForm
.get('accountId')
.removeValidators(Validators.required);
@ -271,12 +267,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
.removeValidators(Validators.required);
this.activityForm.get('dataSource').updateValueAndValidity();
if (
(type === 'FEE' && this.activityForm.get('fee').value === 0) ||
type === 'INTEREST' ||
type === 'LIABILITY'
) {
this.activityForm.get('fee').reset();
if (['INTEREST', 'LIABILITY'].includes(type)) {
this.activityForm.get('fee').setValue(0);
}
this.activityForm.get('name').setValidators(Validators.required);
@ -284,7 +276,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
if (type === 'FEE') {
this.activityForm.get('quantity').setValue(0);
} else if (type === 'INTEREST' || type === 'LIABILITY') {
} else if (['INTEREST', 'LIABILITY'].includes(type)) {
this.activityForm.get('quantity').setValue(1);
}

4
package-lock.json

@ -1,12 +1,12 @@
{
"name": "ghostfolio",
"version": "2.157.1",
"version": "2.158.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ghostfolio",
"version": "2.157.1",
"version": "2.158.0",
"hasInstallScript": true,
"license": "AGPL-3.0",
"dependencies": {

2
package.json

@ -1,6 +1,6 @@
{
"name": "ghostfolio",
"version": "2.157.1",
"version": "2.158.0",
"homepage": "https://ghostfol.io",
"license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio",

2
prisma/schema.prisma

@ -26,6 +26,7 @@ model Access {
}
model Account {
activities Order[]
balance Float @default(0)
balances AccountBalance[]
comment String?
@ -39,7 +40,6 @@ model Account {
userId String
Platform Platform? @relation(fields: [platformId], references: [id])
User User @relation(fields: [userId], onDelete: Cascade, references: [id])
Order Order[]
@@id([id, userId])
@@index([currency])

Loading…
Cancel
Save