Browse Source

Merge branch 'main' into feature/platform-management

pull/1922/head
Thomas Kaul 2 years ago
committed by GitHub
parent
commit
298794bf48
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      CHANGELOG.md
  2. 43
      apps/api/src/app/account/account.service.ts
  3. 1
      apps/api/src/app/import/import.service.ts
  4. 5
      apps/api/src/app/order/create-order.dto.ts
  5. 1
      apps/api/src/app/order/interfaces/activities.interface.ts
  6. 31
      apps/api/src/app/order/order.service.ts
  7. 5
      apps/api/src/app/order/update-order.dto.ts
  8. 10
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  9. 9
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html
  10. 2
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.module.ts
  11. 7
      apps/client/src/app/services/import-activities.service.ts
  12. 8
      package.json
  13. 82
      yarn.lock

7
CHANGELOG.md

@ -9,8 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Introduced the option to update the cash balance of an account when adding an activity
- Added support for the management of platforms in the admin control panel
### Changed
- Upgraded `class-transformer` from version `0.3.2` to `0.5.1`
- Upgraded `class-validator` from version `0.13.1` to `0.14.0`
- Upgraded `prisma` from version `4.12.0` to `4.13.0`
## 1.265.0 - 2023-05-01
### Changed

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

@ -172,4 +172,47 @@ export class AccountService {
where
});
}
public async updateAccountBalance({
accountId,
amount,
currency,
date,
userId
}: {
accountId: string;
amount: number;
currency: string;
date: Date;
userId: string;
}) {
const { balance, currency: currencyOfAccount } = await this.account({
id_userId: {
userId,
id: accountId
}
});
const amountInCurrencyOfAccount =
await this.exchangeRateDataService.toCurrencyAtDate(
amount,
currency,
currencyOfAccount,
date
);
if (amountInCurrencyOfAccount) {
await this.prismaService.account.update({
data: {
balance: new Big(balance).plus(amountInCurrencyOfAccount).toNumber()
},
where: {
id_userId: {
userId,
id: accountId
}
}
});
}
}
}

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

@ -303,6 +303,7 @@ export class ImportService {
}
}
},
updateAccountBalance: false,
User: { connect: { id: userId } }
});
}

5
apps/api/src/app/order/create-order.dto.ts

@ -8,6 +8,7 @@ import {
import { Transform, TransformFnParams } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsEnum,
IsISO8601,
IsNumber,
@ -64,4 +65,8 @@ export class CreateOrderDto {
@IsNumber()
unitPrice: number;
@IsBoolean()
@IsOptional()
updateAccountBalance: boolean;
}

1
apps/api/src/app/order/interfaces/activities.interface.ts

@ -6,6 +6,7 @@ export interface Activities {
export interface Activity extends OrderWithAccount {
feeInBaseCurrency: number;
updateAccountBalance?: boolean;
value: number;
valueInBaseCurrency: number;
}

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

@ -73,6 +73,7 @@ export class OrderService {
dataSource?: DataSource;
symbol?: string;
tags?: Tag[];
updateAccountBalance?: boolean;
userId: string;
}
): Promise<Order> {
@ -89,12 +90,16 @@ export class OrderService {
};
}
const accountId = data.accountId;
let currency = data.currency;
const tags = data.tags ?? [];
const updateAccountBalance = data.updateAccountBalance ?? false;
const userId = data.userId;
if (data.type === 'ITEM') {
const assetClass = data.assetClass;
const assetSubClass = data.assetSubClass;
const currency = data.SymbolProfile.connectOrCreate.create.currency;
currency = data.SymbolProfile.connectOrCreate.create.currency;
const dataSource: DataSource = 'MANUAL';
const id = uuidv4();
const name = data.SymbolProfile.connectOrCreate.create.symbol;
@ -149,11 +154,12 @@ export class OrderService {
delete data.dataSource;
delete data.symbol;
delete data.tags;
delete data.updateAccountBalance;
delete data.userId;
const orderData: Prisma.OrderCreateInput = data;
return this.prismaService.order.create({
const order = await this.prismaService.order.create({
data: {
...orderData,
Account,
@ -165,6 +171,27 @@ export class OrderService {
}
}
});
if (updateAccountBalance === true) {
let amount = new Big(data.unitPrice)
.mul(data.quantity)
.plus(data.fee)
.toNumber();
if (data.type === 'BUY') {
amount = new Big(amount).mul(-1).toNumber();
}
await this.accountService.updateAccountBalance({
accountId,
amount,
currency,
userId,
date: data.date as Date
});
}
return order;
}
public async deleteOrder(

5
apps/api/src/app/order/update-order.dto.ts

@ -8,6 +8,7 @@ import {
import { Transform, TransformFnParams } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsEnum,
IsISO8601,
IsNumber,
@ -66,4 +67,8 @@ export class UpdateOrderDto {
@IsNumber()
unitPrice: number;
@IsBoolean()
@IsOptional()
updateAccountBalance: boolean;
}

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

@ -139,7 +139,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
unitPriceInCustomCurrency: [
this.data.activity?.unitPrice,
Validators.required
]
],
updateAccountBalance: [false]
});
this.activityForm.valueChanges
@ -297,6 +298,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
Validators.required
);
this.activityForm.controls['searchSymbol'].updateValueAndValidity();
this.activityForm.controls['updateAccountBalance'].disable();
this.activityForm.controls['updateAccountBalance'].setValue(false);
} else {
this.activityForm.controls['accountId'].setValidators(
Validators.required
@ -314,6 +317,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
Validators.required
);
this.activityForm.controls['searchSymbol'].updateValueAndValidity();
this.activityForm.controls['updateAccountBalance'].enable();
}
this.changeDetectorRef.markForCheck();
@ -411,7 +415,9 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
: this.activityForm.controls['searchSymbol'].value.symbol,
tags: this.activityForm.controls['tags'].value,
type: this.activityForm.controls['type'].value,
unitPrice: this.activityForm.controls['unitPrice'].value
unitPrice: this.activityForm.controls['unitPrice'].value,
updateAccountBalance:
this.activityForm.controls['updateAccountBalance'].value
};
if (this.data.activity.id) {

9
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html

@ -18,8 +18,8 @@
</mat-select>
</mat-form-field>
</div>
<div class="mb-3">
<mat-form-field appearance="outline" class="w-100">
<div>
<mat-form-field appearance="outline" class="mb-1 without-hint w-100">
<mat-label i18n>Account</mat-label>
<mat-select formControlName="accountId">
<mat-option
@ -32,6 +32,11 @@
</mat-select>
</mat-form-field>
</div>
<div class="mb-3">
<mat-checkbox color="primary" formControlName="updateAccountBalance" i18n
>Update Cash Balance</mat-checkbox
>
</div>
<div
class="mb-3"
[ngClass]="{ 'd-none': !activityForm.controls['searchSymbol'].hasValidator(Validators.required) }"

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

@ -8,6 +8,7 @@ import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
@ -24,6 +25,7 @@ import { CreateOrUpdateActivityDialog } from './create-or-update-activity-dialog
GfValueModule,
MatAutocompleteModule,
MatButtonModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,

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

@ -59,7 +59,8 @@ export class ImportActivitiesService {
quantity: this.parseQuantity({ content, index, item }),
symbol: this.parseSymbol({ content, index, item }),
type: this.parseType({ content, index, item }),
unitPrice: this.parseUnitPrice({ content, index, item })
unitPrice: this.parseUnitPrice({ content, index, item }),
updateAccountBalance: false
});
}
@ -126,7 +127,8 @@ export class ImportActivitiesService {
quantity,
SymbolProfile,
type,
unitPrice
unitPrice,
updateAccountBalance
}: Activity): CreateOrderDto {
return {
accountId,
@ -134,6 +136,7 @@ export class ImportActivitiesService {
quantity,
type,
unitPrice,
updateAccountBalance,
currency: SymbolProfile.currency,
date: date.toString(),
symbol: SymbolProfile.symbol

8
package.json

@ -80,7 +80,7 @@
"@nestjs/schedule": "2.1.0",
"@nestjs/serve-static": "3.0.0",
"@nrwl/angular": "15.9.2",
"@prisma/client": "4.12.0",
"@prisma/client": "4.13.0",
"@simplewebauthn/browser": "5.2.1",
"@simplewebauthn/server": "5.2.1",
"@stripe/stripe-js": "1.47.0",
@ -97,8 +97,8 @@
"chartjs-plugin-annotation": "2.1.2",
"chartjs-plugin-datalabels": "2.2.0",
"cheerio": "1.0.0-rc.12",
"class-transformer": "0.3.2",
"class-validator": "0.13.1",
"class-transformer": "0.5.1",
"class-validator": "0.14.0",
"color": "4.2.3",
"countries-and-timezones": "3.4.1",
"countries-list": "2.6.1",
@ -120,7 +120,7 @@
"passport": "0.6.0",
"passport-google-oauth20": "2.0.0",
"passport-jwt": "4.0.0",
"prisma": "4.12.0",
"prisma": "4.13.0",
"reflect-metadata": "0.1.13",
"rxjs": "7.5.6",
"stripe": "11.12.0",

82
yarn.lock

@ -4887,22 +4887,22 @@
dependencies:
esquery "^1.0.1"
"@prisma/client@4.12.0":
version "4.12.0"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.12.0.tgz#119b692888b1fe0fd3305c7d0e0ac48520aa6839"
integrity sha512-j9/ighfWwux97J2dS15nqhl60tYoH8V0IuSsgZDb6bCFcQD3fXbXmxjYC8GHhIgOk3lB7Pq+8CwElz2MiDpsSg==
"@prisma/client@4.13.0":
version "4.13.0"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.13.0.tgz#271d2b9756503ea17bbdb459c7995536cf2a6191"
integrity sha512-YaiiICcRB2hatxsbnfB66uWXjcRw3jsZdlAVxmx0cFcTc/Ad/sKdHCcWSnqyDX47vAewkjRFwiLwrOUjswVvmA==
dependencies:
"@prisma/engines-version" "4.12.0-67.659ef412370fa3b41cd7bf6e94587c1dfb7f67e7"
"@prisma/engines-version" "4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a"
"@prisma/engines-version@4.12.0-67.659ef412370fa3b41cd7bf6e94587c1dfb7f67e7":
version "4.12.0-67.659ef412370fa3b41cd7bf6e94587c1dfb7f67e7"
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.12.0-67.659ef412370fa3b41cd7bf6e94587c1dfb7f67e7.tgz#51a1cc5c886564b542acde64a873645d0dee2566"
integrity sha512-JIHNj5jlXb9mcaJwakM0vpgRYJIAurxTUqM0iX0tfEQA5XLZ9ONkIckkhuAKdAzocZ+80GYg7QSsfpjg7OxbOA==
"@prisma/engines-version@4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a":
version "4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a"
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.13.0-50.1e7af066ee9cb95cf3a403c78d9aab3e6b04f37a.tgz#ae338908d11685dee50e7683502d75442b955bf9"
integrity sha512-fsQlbkhPJf08JOzKoyoD9atdUijuGBekwoOPZC3YOygXEml1MTtgXVpnUNchQlRSY82OQ6pSGQ9PxUe4arcSLQ==
"@prisma/engines@4.12.0":
version "4.12.0"
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.12.0.tgz#68d99078b70b2d9c339d0e8cbf2e99f00b72aa8c"
integrity sha512-0alKtnxhNB5hYU+ymESBlGI4b9XrGGSdv7Ud+8TE/fBNOEhIud0XQsAR+TrvUZgS4na5czubiMsODw0TUrgkIA==
"@prisma/engines@4.13.0":
version "4.13.0"
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.13.0.tgz#582a6b90b6efeb0f465984f1fe0e72a4afaaa5ae"
integrity sha512-HrniowHRZXHuGT9XRgoXEaP2gJLXM5RMoItaY2PkjvuZ+iHc0Zjbm/302MB8YsPdWozAPHHn+jpFEcEn71OgPw==
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.1"
@ -6406,10 +6406,10 @@
resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
"@types/validator@^13.1.3":
version "13.7.3"
resolved "https://registry.npmjs.org/@types/validator/-/validator-13.7.3.tgz"
integrity sha512-DNviAE5OUcZ5s+XEQHRhERLg8fOp8gSgvyJ4aaFASx5wwaObm+PBwTIMXiOFm1QrSee5oYwEAYb7LMzX2O88gA==
"@types/validator@^13.7.10":
version "13.7.15"
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.15.tgz#408c99d1b5f0eecc78109c11f896f72d1f026a10"
integrity sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ==
"@types/webpack-env@^1.16.0":
version "1.17.0"
@ -8787,10 +8787,10 @@ cjs-module-lexer@^1.0.0:
resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz"
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
class-transformer@0.3.2:
version "0.3.2"
resolved "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.2.tgz"
integrity sha512-9QY6QXBH/+Gt1C3HBmJCrgY6+EFpIa6aLjfDnlXFx0zQl/HjrCE7qoaI0srNrxpMIfsobCpgUdDG5JYtJOpVsw==
class-transformer@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336"
integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==
class-utils@^0.3.5:
version "0.3.6"
@ -8802,14 +8802,14 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
class-validator@0.13.1:
version "0.13.1"
resolved "https://registry.npmjs.org/class-validator/-/class-validator-0.13.1.tgz"
integrity sha512-zWIeYFhUitvAHBwNhDdCRK09hWx+P0HUwFE8US8/CxFpMVzkUK8RJl7yOIE+BVu2lxyPNgeOaFv78tLE47jBIg==
class-validator@0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.14.0.tgz#40ed0ecf3c83b2a8a6a320f4edb607be0f0df159"
integrity sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==
dependencies:
"@types/validator" "^13.1.3"
libphonenumber-js "^1.9.7"
validator "^13.5.2"
"@types/validator" "^13.7.10"
libphonenumber-js "^1.10.14"
validator "^13.7.0"
clean-css@^4.2.3:
version "4.2.4"
@ -15412,10 +15412,10 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"
libphonenumber-js@^1.9.7:
version "1.10.6"
resolved "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.6.tgz"
integrity sha512-CIjT100/SmntsUjsLVs2t3ufeN4KdNXUxhD07tH153pdbaCWuAjv0jK/gPuywR3IImB/U/MQM+x9RfhMs5XZiA==
libphonenumber-js@^1.10.14:
version "1.10.28"
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.28.tgz#cae7e929cad96cee5ecc9449027192ecba39ee72"
integrity sha512-1eAgjLrZA0+2Wgw4hs+4Q/kEBycxQo8ZLYnmOvZ3AlM8ImAVAJgDPlZtISLEzD1vunc2q8s2Pn7XwB7I8U3Kzw==
license-webpack-plugin@4.0.2, license-webpack-plugin@^4.0.2:
version "4.0.2"
@ -18083,12 +18083,12 @@ pretty-hrtime@^1.0.3:
resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz"
integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==
prisma@4.12.0:
version "4.12.0"
resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.12.0.tgz#1080eda951928cb3b0274ad29da9ae4f93143d68"
integrity sha512-xqVper4mbwl32BWzLpdznHAYvYDWQQWK2tBfXjdUD397XaveRyAP7SkBZ6kFlIg8kKayF4hvuaVtYwXd9BodAg==
prisma@4.13.0:
version "4.13.0"
resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.13.0.tgz#0b83f40acf50cd47d7463a135c4e9b275713e602"
integrity sha512-L9mqjnSmvWIRCYJ9mQkwCtj4+JDYYTdhoyo8hlsHNDXaZLh/b4hR0IoKIBbTKxZuyHQzLopb/+0Rvb69uGV7uA==
dependencies:
"@prisma/engines" "4.12.0"
"@prisma/engines" "4.13.0"
prismjs@^1.28.0:
version "1.28.0"
@ -21151,10 +21151,10 @@ validate-npm-package-name@^5.0.0:
dependencies:
builtins "^5.0.0"
validator@^13.5.2:
version "13.7.0"
resolved "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz"
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
validator@^13.7.0:
version "13.9.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855"
integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==
vary@^1, vary@~1.1.2:
version "1.1.2"

Loading…
Cancel
Save