Browse Source

Refactoring

pull/3190/head
Thomas Kaul 1 year ago
parent
commit
4e66efaa11
  1. 16
      apps/api/src/app/order/order.service.ts
  2. 5
      apps/api/src/app/portfolio/portfolio.controller.ts
  3. 123
      apps/api/src/app/portfolio/portfolio.service.ts
  4. 2
      apps/api/src/app/user/update-user-setting.dto.ts
  5. 54
      apps/client/src/app/components/investment-chart/investment-chart.component.ts

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

@ -198,22 +198,26 @@ export class OrderService {
} }
public async getOrders({ public async getOrders({
endDate,
filters, filters,
includeDrafts = false, includeDrafts = false,
skip, skip,
sortColumn, sortColumn,
sortDirection, sortDirection,
startDate,
take = Number.MAX_SAFE_INTEGER, take = Number.MAX_SAFE_INTEGER,
types, types,
userCurrency, userCurrency,
userId, userId,
withExcludedAccounts = false withExcludedAccounts = false
}: { }: {
endDate?: Date;
filters?: Filter[]; filters?: Filter[];
includeDrafts?: boolean; includeDrafts?: boolean;
skip?: number; skip?: number;
sortColumn?: string; sortColumn?: string;
sortDirection?: Prisma.SortOrder; sortDirection?: Prisma.SortOrder;
startDate?: Date;
take?: number; take?: number;
types?: ActivityType[]; types?: ActivityType[];
userCurrency: string; userCurrency: string;
@ -225,6 +229,18 @@ export class OrderService {
]; ];
const where: Prisma.OrderWhereInput = { userId }; const where: Prisma.OrderWhereInput = { userId };
if (endDate || startDate) {
where.AND = [];
if (endDate) {
where.AND.push({ date: { lte: endDate } });
}
if (startDate) {
where.AND.push({ date: { gt: startDate } });
}
}
const { const {
ACCOUNT: filtersByAccount, ACCOUNT: filtersByAccount,
ASSET_CLASS: filtersByAssetClass, ASSET_CLASS: filtersByAssetClass,

5
apps/api/src/app/portfolio/portfolio.controller.ts

@ -236,8 +236,12 @@ export class PortfolioController {
await this.impersonationService.validateImpersonationId(impersonationId); await this.impersonationService.validateImpersonationId(impersonationId);
const userCurrency = this.request.user.Settings.settings.baseCurrency; const userCurrency = this.request.user.Settings.settings.baseCurrency;
const { endDate, startDate } = this.portfolioService.getInterval(dateRange);
const { activities } = await this.orderService.getOrders({ const { activities } = await this.orderService.getOrders({
endDate,
filters, filters,
startDate,
userCurrency, userCurrency,
userId: impersonationUserId || this.request.user.id, userId: impersonationUserId || this.request.user.id,
types: ['DIVIDEND'] types: ['DIVIDEND']
@ -245,7 +249,6 @@ export class PortfolioController {
let dividends = await this.portfolioService.getDividends({ let dividends = await this.portfolioService.getDividends({
activities, activities,
dateRange,
groupBy groupBy
}); });

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

@ -87,7 +87,7 @@ import {
endOfDay, endOfDay,
endOfYear endOfYear
} from 'date-fns'; } from 'date-fns';
import { isEmpty, last, uniq, uniqBy } from 'lodash'; import { first, isEmpty, last, uniq, uniqBy } from 'lodash';
import { PortfolioCalculator } from './calculator/twr/portfolio-calculator'; import { PortfolioCalculator } from './calculator/twr/portfolio-calculator';
import { import {
@ -224,11 +224,9 @@ export class PortfolioService {
public async getDividends({ public async getDividends({
activities, activities,
dateRange = 'max',
groupBy groupBy
}: { }: {
activities: Activity[]; activities: Activity[];
dateRange?: DateRange;
groupBy?: GroupBy; groupBy?: GroupBy;
}): Promise<InvestmentItem[]> { }): Promise<InvestmentItem[]> {
let dividends = activities.map(({ date, valueInBaseCurrency }) => { let dividends = activities.map(({ date, valueInBaseCurrency }) => {
@ -242,14 +240,50 @@ export class PortfolioService {
dividends = this.getDividendsByGroup({ dividends, groupBy }); dividends = this.getDividendsByGroup({ dividends, groupBy });
} }
const { startDate } = this.getInterval( return dividends;
dateRange, }
parseDate(dividends[0]?.date)
);
return dividends.filter(({ date }) => { public getInterval(aDateRange: DateRange, portfolioStart = new Date(0)) {
return !isBefore(parseDate(date), startDate); let endDate = endOfDay(new Date());
}); let startDate = portfolioStart;
switch (aDateRange) {
case '1d':
startDate = max([startDate, subDays(resetHours(new Date()), 1)]);
break;
case 'mtd':
startDate = max([
startDate,
subDays(startOfMonth(resetHours(new Date())), 1)
]);
break;
case 'wtd':
startDate = max([
startDate,
subDays(startOfWeek(resetHours(new Date()), { weekStartsOn: 1 }), 1)
]);
break;
case 'ytd':
startDate = max([
startDate,
subDays(startOfYear(resetHours(new Date())), 1)
]);
break;
case '1y':
startDate = max([startDate, subYears(resetHours(new Date()), 1)]);
break;
case '5y':
startDate = max([startDate, subYears(resetHours(new Date()), 5)]);
break;
case 'max':
break;
default:
// '2024', '2023', '2022', etc.
endDate = endOfYear(new Date(aDateRange));
startDate = max([startDate, new Date(aDateRange)]);
}
return { endDate, startDate };
} }
public async getInvestments({ public async getInvestments({
@ -963,7 +997,10 @@ export class PortfolioService {
const userId = await this.getUserId(impersonationId, this.request.user.id); const userId = await this.getUserId(impersonationId, this.request.user.id);
const user = await this.userService.user({ id: userId }); const user = await this.userService.user({ id: userId });
const { endDate, startDate } = this.getInterval(dateRange);
const { activities } = await this.orderService.getOrders({ const { activities } = await this.orderService.getOrders({
endDate,
filters, filters,
userId, userId,
types: ['BUY', 'SELL'], types: ['BUY', 'SELL'],
@ -984,12 +1021,10 @@ export class PortfolioService {
exchangeRateDataService: this.exchangeRateDataService exchangeRateDataService: this.exchangeRateDataService
}); });
const { startDate } = this.getInterval( const currentPositions = await portfolioCalculator.getCurrentPositions(
dateRange, startDate,
portfolioCalculator.getStartDate() endDate
); );
const currentPositions =
await portfolioCalculator.getCurrentPositions(startDate);
let positions = currentPositions.positions.filter(({ quantity }) => { let positions = currentPositions.positions.filter(({ quantity }) => {
return !quantity.eq(0); return !quantity.eq(0);
@ -1136,7 +1171,10 @@ export class PortfolioService {
) )
); );
const { endDate, startDate } = this.getInterval(dateRange);
const { activities } = await this.orderService.getOrders({ const { activities } = await this.orderService.getOrders({
endDate,
filters, filters,
userCurrency, userCurrency,
userId, userId,
@ -1172,16 +1210,6 @@ export class PortfolioService {
exchangeRateDataService: this.exchangeRateDataService exchangeRateDataService: this.exchangeRateDataService
}); });
const portfolioStart = min(
[
parseDate(accountBalanceItems[0]?.date),
portfolioCalculator.getStartDate()
].filter((date) => {
return isValid(date);
})
);
const { startDate } = this.getInterval(dateRange, portfolioStart);
const { const {
currentValueInBaseCurrency, currentValueInBaseCurrency,
errors, errors,
@ -1195,7 +1223,7 @@ export class PortfolioService {
netPerformancePercentageWithCurrencyEffect, netPerformancePercentageWithCurrencyEffect,
netPerformanceWithCurrencyEffect, netPerformanceWithCurrencyEffect,
totalInvestment totalInvestment
} = await portfolioCalculator.getCurrentPositions(startDate); // TODO: Provide endDate } = await portfolioCalculator.getCurrentPositions(startDate, endDate);
let currentNetPerformance = netPerformance; let currentNetPerformance = netPerformance;
@ -1620,49 +1648,6 @@ export class PortfolioService {
}; };
} }
private getInterval(aDateRange: DateRange, portfolioStart: Date) {
let endDate = endOfDay(new Date());
let startDate = portfolioStart;
switch (aDateRange) {
case '1d':
startDate = max([startDate, subDays(resetHours(new Date()), 1)]);
break;
case 'mtd':
startDate = max([
startDate,
subDays(startOfMonth(resetHours(new Date())), 1)
]);
break;
case 'wtd':
startDate = max([
startDate,
subDays(startOfWeek(resetHours(new Date()), { weekStartsOn: 1 }), 1)
]);
break;
case 'ytd':
startDate = max([
startDate,
subDays(startOfYear(resetHours(new Date())), 1)
]);
break;
case '1y':
startDate = max([startDate, subYears(resetHours(new Date()), 1)]);
break;
case '5y':
startDate = max([startDate, subYears(resetHours(new Date()), 5)]);
break;
case 'max':
break;
default:
// '2024', '2023', '2022', etc.
endDate = endOfYear(new Date(aDateRange));
startDate = max([startDate, new Date(aDateRange)]);
}
return { endDate, startDate };
}
private getStreaks({ private getStreaks({
investments, investments,
savingsRate savingsRate

2
apps/api/src/app/user/update-user-setting.dto.ts

@ -41,7 +41,7 @@ export class UpdateUserSettingDto {
'mtd', 'mtd',
'wtd', 'wtd',
'ytd', 'ytd',
...eachYearOfInterval({ end: new Date(), start: new Date(1900) }).map( ...eachYearOfInterval({ end: new Date(), start: new Date(0) }).map(
(date) => { (date) => {
return format(date, 'yyyy'); return format(date, 'yyyy');
} }

54
apps/client/src/app/components/investment-chart/investment-chart.component.ts

@ -6,7 +6,6 @@ import {
} from '@ghostfolio/common/chart-helper'; } from '@ghostfolio/common/chart-helper';
import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config'; import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config';
import { import {
DATE_FORMAT,
getBackgroundColor, getBackgroundColor,
getDateFormatString, getDateFormatString,
getLocale, getLocale,
@ -39,16 +38,8 @@ import {
} from 'chart.js'; } from 'chart.js';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import annotationPlugin from 'chartjs-plugin-annotation'; import annotationPlugin from 'chartjs-plugin-annotation';
import { import { isAfter, isValid, min, subDays } from 'date-fns';
addDays, import { first } from 'lodash';
format,
isAfter,
isValid,
min,
parseISO,
subDays
} from 'date-fns';
import { first, last } from 'lodash';
@Component({ @Component({
selector: 'gf-investment-chart', selector: 'gf-investment-chart',
@ -112,46 +103,6 @@ export class InvestmentChartComponent implements OnChanges, OnDestroy {
Object.assign({}, item) Object.assign({}, item)
); );
if (!this.groupBy && this.investments?.length > 0) {
let date: string;
if (this.range === 'max') {
// Extend chart by 5% of days in market (before)
date = format(
subDays(
parseISO(this.investments[0].date),
this.daysInMarket * 0.05 || 90
),
DATE_FORMAT
);
this.investments.unshift({
date,
investment: 0
});
this.values.unshift({
date,
value: 0
});
}
// Extend chart by 5% of days in market (after)
date = format(
addDays(
parseDate(last(this.investments).date),
this.daysInMarket * 0.05 || 90
),
DATE_FORMAT
);
this.investments.push({
date,
investment: last(this.investments).investment
});
this.values.push({
date,
value: last(this.values).value
});
}
const chartData: ChartData<'bar' | 'line'> = { const chartData: ChartData<'bar' | 'line'> = {
labels: this.historicalDataItems.map(({ date }) => { labels: this.historicalDataItems.map(({ date }) => {
return parseDate(date); return parseDate(date);
@ -303,7 +254,6 @@ export class InvestmentChartComponent implements OnChanges, OnDestroy {
display: false display: false
}, },
min: scaleXMin, min: scaleXMin,
suggestedMax: new Date().toISOString(),
type: 'time', type: 'time',
time: { time: {
tooltipFormat: getDateFormatString(this.locale), tooltipFormat: getDateFormatString(this.locale),

Loading…
Cancel
Save