Browse Source

Fix savings rate in impersonation mode

pull/7522/head
Thomas Kaul 4 weeks ago
parent
commit
4dcf98b126
  1. 8
      apps/api/src/app/portfolio/portfolio.controller.ts
  2. 5
      apps/api/src/app/portfolio/portfolio.service.ts
  3. 4
      apps/client/src/app/app.component.ts
  4. 4
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
  5. 2
      apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts
  6. 17
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  7. 1
      libs/common/src/lib/interfaces/responses/portfolio-investments.interface.ts
  8. 4
      libs/common/src/lib/permissions.ts

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

@ -491,12 +491,12 @@ export class PortfolioController {
filterByTags: tags filterByTags: tags
}); });
let { investments, streaks } = await this.portfolioService.getInvestments({ let { investments, savingsRate, streaks } =
await this.portfolioService.getInvestments({
filters, filters,
groupBy, groupBy,
impersonationId, impersonationId,
dateRange: range, dateRange: range,
savingsRate: this.request.user?.settings?.settings.savingsRate,
userId: this.request.user.id userId: this.request.user.id
}); });
@ -521,6 +521,8 @@ export class PortfolioController {
'currentStreak', 'currentStreak',
'longestStreak' 'longestStreak'
]); ]);
savingsRate = null;
} }
if ( if (
@ -537,7 +539,7 @@ export class PortfolioController {
]); ]);
} }
return { investments, streaks }; return { investments, savingsRate, streaks };
} }
@Get('performance') @Get('performance')

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

@ -413,19 +413,18 @@ export class PortfolioService {
filters, filters,
groupBy, groupBy,
impersonationId, impersonationId,
savingsRate,
userId userId
}: { }: {
dateRange: DateRange; dateRange: DateRange;
filters?: Filter[]; filters?: Filter[];
groupBy?: GroupBy; groupBy?: GroupBy;
impersonationId: string; impersonationId: string;
savingsRate: number;
userId: string; userId: string;
}): Promise<PortfolioInvestmentsResponse> { }): Promise<PortfolioInvestmentsResponse> {
userId = await this.getUserId(impersonationId, userId); userId = await this.getUserId(impersonationId, userId);
const user = await this.userService.user({ id: userId }); const user = await this.userService.user({ id: userId });
const userCurrency = this.getUserCurrency(user); const userCurrency = this.getUserCurrency(user);
const savingsRate = (user.settings?.settings as UserSettings)?.savingsRate;
const { endDate, startDate } = getIntervalFromDateRange({ dateRange }); const { endDate, startDate } = getIntervalFromDateRange({ dateRange });
@ -438,6 +437,7 @@ export class PortfolioService {
if (activities.length === 0) { if (activities.length === 0) {
return { return {
savingsRate,
investments: [], investments: [],
streaks: { currentStreak: 0, longestStreak: 0 } streaks: { currentStreak: 0, longestStreak: 0 }
}; };
@ -484,6 +484,7 @@ export class PortfolioService {
return { return {
investments, investments,
savingsRate,
streaks streaks
}; };
} }

4
apps/client/src/app/app.component.ts

@ -63,6 +63,7 @@ export class GfAppComponent implements OnInit {
public hasPermissionToChangeFilters: boolean; public hasPermissionToChangeFilters: boolean;
public hasPromotion = false; public hasPromotion = false;
public hasTabs = false; public hasTabs = false;
public impersonationId: string | null;
public info: InfoItem; public info: InfoItem;
public pageTitle: string; public pageTitle: string;
public routerLinkRegister = publicRoutes.register.routerLink; public routerLinkRegister = publicRoutes.register.routerLink;
@ -117,6 +118,7 @@ export class GfAppComponent implements OnInit {
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((impersonationId) => { .subscribe((impersonationId) => {
this.hasImpersonationId = !!impersonationId; this.hasImpersonationId = !!impersonationId;
this.impersonationId = impersonationId;
}); });
this.router.events this.router.events
@ -291,7 +293,6 @@ export class GfAppComponent implements OnInit {
baseCurrency: this.user?.settings?.baseCurrency, baseCurrency: this.user?.settings?.baseCurrency,
colorScheme: this.user?.settings?.colorScheme, colorScheme: this.user?.settings?.colorScheme,
deviceType: this.deviceType, deviceType: this.deviceType,
hasImpersonationId: this.hasImpersonationId,
hasPermissionToAccessAdminControl: hasPermission( hasPermissionToAccessAdminControl: hasPermission(
this.user?.permissions, this.user?.permissions,
permissions.accessAdminControl permissions.accessAdminControl
@ -314,6 +315,7 @@ export class GfAppComponent implements OnInit {
permissions.updateActivity permissions.updateActivity
) && ) &&
!this.user?.settings?.isRestrictedView, !this.user?.settings?.isRestrictedView,
impersonationId: this.impersonationId,
locale: this.user?.settings?.locale locale: this.user?.settings?.locale
}, },
height: this.deviceType === 'mobile' ? '98vh' : '80vh', height: this.deviceType === 'mobile' ? '98vh' : '80vh',

4
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html

@ -382,7 +382,7 @@
[hasPermissionToCreateActivity]="false" [hasPermissionToCreateActivity]="false"
[hasPermissionToDeleteActivity]="false" [hasPermissionToDeleteActivity]="false"
[hasPermissionToExportActivities]=" [hasPermissionToExportActivities]="
!data.hasImpersonationId && !user?.settings?.isRestrictedView !data.impersonationId && !user?.settings?.isRestrictedView
" "
[hasPermissionToFilter]="false" [hasPermissionToFilter]="false"
[hasPermissionToOpenDetails]="false" [hasPermissionToOpenDetails]="false"
@ -390,8 +390,8 @@
[pageIndex]="pageIndex" [pageIndex]="pageIndex"
[pageSize]="pageSize" [pageSize]="pageSize"
[showActions]=" [showActions]="
!data.hasImpersonationId &&
data.hasPermissionToCreateActivity && data.hasPermissionToCreateActivity &&
!data.impersonationId &&
user?.settings?.isExperimentalFeatures && user?.settings?.isExperimentalFeatures &&
!user?.settings?.isRestrictedView !user?.settings?.isRestrictedView
" "

2
apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts

@ -7,11 +7,11 @@ export interface HoldingDetailDialogParams {
colorScheme: ColorScheme; colorScheme: ColorScheme;
dataSource: DataSource; dataSource: DataSource;
deviceType: string; deviceType: string;
hasImpersonationId: boolean;
hasPermissionToAccessAdminControl: boolean; hasPermissionToAccessAdminControl: boolean;
hasPermissionToCreateActivity: boolean; hasPermissionToCreateActivity: boolean;
hasPermissionToReportDataGlitch: boolean; hasPermissionToReportDataGlitch: boolean;
hasPermissionToUpdateActivity: boolean; hasPermissionToUpdateActivity: boolean;
impersonationId: string | null;
locale: string; locale: string;
symbol: string; symbol: string;
} }

17
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -83,7 +83,6 @@ export class GfAnalysisPageComponent implements OnInit {
protected bottom3: PortfolioPosition[]; protected bottom3: PortfolioPosition[];
protected dividendsByGroup: InvestmentItem[]; protected dividendsByGroup: InvestmentItem[];
protected readonly dividendTimelineDataLabel = $localize`Dividend`; protected readonly dividendTimelineDataLabel = $localize`Dividend`;
protected hasImpersonationId: boolean;
protected hasPermissionToReadAiPrompt: boolean; protected hasPermissionToReadAiPrompt: boolean;
protected impersonationId: string | null; protected impersonationId: string | null;
protected investments: InvestmentItem[]; protected investments: InvestmentItem[];
@ -105,6 +104,7 @@ export class GfAnalysisPageComponent implements OnInit {
protected performanceDataItemsInPercentage: HistoricalDataItem[]; protected performanceDataItemsInPercentage: HistoricalDataItem[];
protected readonly portfolioEvolutionDataLabel = $localize`Investment`; protected readonly portfolioEvolutionDataLabel = $localize`Investment`;
protected precision = 2; protected precision = 2;
protected savingsRatePerMonth: number;
protected streaks: PortfolioInvestmentsResponse['streaks']; protected streaks: PortfolioInvestmentsResponse['streaks'];
protected top3: PortfolioPosition[]; protected top3: PortfolioPosition[];
protected unitCurrentStreak: string; protected unitCurrentStreak: string;
@ -136,18 +136,13 @@ export class GfAnalysisPageComponent implements OnInit {
} }
get savingsRate() { get savingsRate() {
const savingsRatePerMonth = if (!this.savingsRatePerMonth) {
this.hasImpersonationId || this.user.settings.isRestrictedView
? undefined
: this.user?.settings?.savingsRate;
if (savingsRatePerMonth === undefined) {
return undefined; return undefined;
} }
return this.mode() === 'year' return this.mode() === 'year'
? savingsRatePerMonth * 12 ? this.savingsRatePerMonth * 12
: savingsRatePerMonth; : this.savingsRatePerMonth;
} }
public ngOnInit() { public ngOnInit() {
@ -155,7 +150,6 @@ export class GfAnalysisPageComponent implements OnInit {
.onChangeHasImpersonation() .onChangeHasImpersonation()
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((impersonationId) => { .subscribe((impersonationId) => {
this.hasImpersonationId = !!impersonationId;
this.impersonationId = impersonationId; this.impersonationId = impersonationId;
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
@ -282,8 +276,9 @@ export class GfAnalysisPageComponent implements OnInit {
range: this.user?.settings?.dateRange ?? DEFAULT_DATE_RANGE range: this.user?.settings?.dateRange ?? DEFAULT_DATE_RANGE
}) })
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(({ investments, streaks }) => { .subscribe(({ investments, savingsRate, streaks }) => {
this.investmentsByGroup = investments; this.investmentsByGroup = investments;
this.savingsRatePerMonth = savingsRate;
this.streaks = streaks; this.streaks = streaks;
this.unitCurrentStreak = this.unitCurrentStreak =
this.mode() === 'year' this.mode() === 'year'

1
libs/common/src/lib/interfaces/responses/portfolio-investments.interface.ts

@ -2,5 +2,6 @@ import { InvestmentItem } from '../investment-item.interface';
export interface PortfolioInvestmentsResponse { export interface PortfolioInvestmentsResponse {
investments: InvestmentItem[]; investments: InvestmentItem[];
savingsRate: number;
streaks: { currentStreak: number; longestStreak: number }; streaks: { currentStreak: number; longestStreak: number };
} }

4
libs/common/src/lib/permissions.ts

@ -201,14 +201,14 @@ export function hasReadRestrictedAccessPermission({
accesses = [], accesses = [],
impersonationId impersonationId
}: { }: {
accesses: Pick<Access, 'id' | 'permissions'>[]; accesses?: Pick<Access, 'id' | 'permissions'>[];
impersonationId: string | null; impersonationId: string | null;
}) { }) {
if (!impersonationId) { if (!impersonationId) {
return false; return false;
} }
const access = accesses?.find(({ id }) => { const access = accesses.find(({ id }) => {
return id === impersonationId; return id === impersonationId;
}); });

Loading…
Cancel
Save