diff --git a/CHANGELOG.md b/CHANGELOG.md index bb550c2fd..1311c54ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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 + +### Added + +- Added support for liabilities + ## 1.279.0 - 2023-06-10 ### Added diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index 696f5442e..cc9718e7d 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -96,7 +96,7 @@ export class OrderService { const updateAccountBalance = data.updateAccountBalance ?? false; const userId = data.userId; - if (data.type === 'ITEM') { + if (data.type === 'ITEM' || data.type === 'LIABILITY') { const assetClass = data.assetClass; const assetSubClass = data.assetSubClass; currency = data.SymbolProfile.connectOrCreate.create.currency; @@ -129,7 +129,10 @@ export class OrderService { } }); - const isDraft = isAfter(data.date as Date, endOfToday()); + const isDraft = + data.type === 'LIABILITY' + ? false + : isAfter(data.date as Date, endOfToday()); if (!isDraft) { // Gather symbol data of order in the background, if not draft @@ -320,7 +323,11 @@ export class OrderService { }) ) .filter((order) => { - return withExcludedAccounts || order.Account?.isExcluded === false; + return ( + withExcludedAccounts || + !order.Account || + order.Account?.isExcluded === false + ); }) .map((order) => { const value = new Big(order.quantity).mul(order.unitPrice).toNumber(); diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 1747936fd..06f841e12 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -162,6 +162,7 @@ export class PortfolioController { 'excludedAccountsAndActivities', 'fees', 'items', + 'liabilities', 'netWorth', 'totalBuy', 'totalSell' diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index aea522f40..66f3841a4 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1302,12 +1302,11 @@ export class PortfolioService { }: { activities: OrderWithAccount[]; date?: Date; - userCurrency: string; }) { return activities .filter((activity) => { - // Filter out all activities before given date and type dividend + // Filter out all activities before given date (drafts) and type dividend return ( isBefore(date, new Date(activity.date)) && activity.type === TypeOfOrder.DIVIDEND @@ -1431,7 +1430,7 @@ export class PortfolioService { }) { return activities .filter((activity) => { - // Filter out all activities before given date + // Filter out all activities before given date (drafts) return isBefore(date, new Date(activity.date)); }) .map(({ fee, SymbolProfile }) => { @@ -1478,19 +1477,37 @@ export class PortfolioService { }; } - private getItems(orders: OrderWithAccount[], date = new Date(0)) { - return orders - .filter((order) => { - // Filter out all orders before given date and type item + private getItems(activities: OrderWithAccount[], date = new Date(0)) { + return activities + .filter((activity) => { + // Filter out all activities before given date (drafts) and type item return ( - isBefore(date, new Date(order.date)) && - order.type === TypeOfOrder.ITEM + isBefore(date, new Date(activity.date)) && + activity.type === TypeOfOrder.ITEM ); }) - .map((order) => { + .map(({ quantity, SymbolProfile, unitPrice }) => { return this.exchangeRateDataService.toCurrency( - new Big(order.quantity).mul(order.unitPrice).toNumber(), - order.SymbolProfile.currency, + new Big(quantity).mul(unitPrice).toNumber(), + SymbolProfile.currency, + this.request.user.Settings.settings.baseCurrency + ); + }) + .reduce( + (previous, current) => new Big(previous).plus(current), + new Big(0) + ); + } + + private getLiabilities(activities: OrderWithAccount[]) { + return activities + .filter(({ type }) => { + return type === TypeOfOrder.LIABILITY; + }) + .map(({ quantity, SymbolProfile, unitPrice }) => { + return this.exchangeRateDataService.toCurrency( + new Big(quantity).mul(unitPrice).toNumber(), + SymbolProfile.currency, this.request.user.Settings.settings.baseCurrency ); }) @@ -1601,6 +1618,7 @@ export class PortfolioService { const fees = this.getFees({ activities, userCurrency }).toNumber(); const firstOrderDate = activities[0]?.date; const items = this.getItems(activities).toNumber(); + const liabilities = this.getLiabilities(activities).toNumber(); const totalBuy = this.getTotalByType(activities, userCurrency, 'BUY'); const totalSell = this.getTotalByType(activities, userCurrency, 'SELL'); @@ -1633,6 +1651,7 @@ export class PortfolioService { .plus(performanceInformation.performance.currentValue) .plus(items) .plus(excludedAccountsAndActivities) + .minus(liabilities) .toNumber(); const daysInMarket = differenceInDays(new Date(), firstOrderDate); @@ -1659,6 +1678,7 @@ export class PortfolioService { fees, firstOrderDate, items, + liabilities, netWorth, totalBuy, totalSell, diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html index 8b507f553..3ceadb048 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -194,6 +194,26 @@