Browse Source

fix minor issues from feedback

pull/6258/head
Sven Günther 1 day ago
parent
commit
8834c1c1b1
  1. 10
      CHANGELOG.md
  2. 119
      CLAUDE.md
  3. 4
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  4. 2
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts
  5. 3
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts
  6. 2
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts
  7. 4
      apps/api/src/app/portfolio/portfolio.service.ts
  8. 2
      libs/common/src/lib/interfaces/portfolio-summary.interface.ts
  9. 3
      libs/common/src/lib/models/portfolio-snapshot.ts
  10. 3
      libs/common/src/lib/models/timeline-position.ts

10
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 the dividend yield (trailing twelve months) to the portfolio summary (experimental)
## 2.237.0 - 2026-02-08
### Changed
@ -48,10 +54,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## 2.234.0 - 2026-01-30
### Added
- Added the annualized dividend yield to the portfolio summary (experimental)
### Changed
- Improved the usability of the create asset profile dialog in the market data section of the admin control panel

119
CLAUDE.md

@ -1,119 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Ghostfolio is an open source wealth management software built with TypeScript in an Nx monorepo workspace. It's a full-stack application with Angular frontend and NestJS backend, using PostgreSQL with Prisma ORM and Redis for caching.
## Development Commands
### Environment Setup
```bash
npm install
docker compose -f docker/docker-compose.dev.yml up -d # Start PostgreSQL and Redis
npm run database:setup # Initialize database schema
```
### Development Servers
```bash
npm run start:server # Start NestJS API server
npm run start:client # Start Angular client (English)
npm run watch:server # Start server in watch mode for debugging
```
### Build and Production
```bash
npm run build:production # Build both API and client for production
npm run start:production # Run production build with database migration
```
### Database Operations
```bash
npm run database:push # Sync schema with database (development)
npm run database:migrate # Apply migrations (production)
npm run database:seed # Seed database with initial data
npm run database:gui # Open Prisma Studio
npm run database:format-schema # Format Prisma schema
npm run database:generate-typings # Generate Prisma client
```
### Testing and Quality
```bash
npm test # Run all tests (API + common)
npm run test:api # Run API tests only
npm run test:common # Run common library tests
npm run test:single # Run single test file (example provided)
npm run lint # Run ESLint on all projects
npm run format # Format code with Prettier
npm run format:check # Check code formatting
```
### Nx Workspace Commands
```bash
nx affected:build # Build affected projects
nx affected:test # Test affected projects
nx affected:lint # Lint affected projects
nx dep-graph # View dependency graph
```
### Storybook (Component Library)
```bash
npm run start:storybook # Start Storybook development server
npm run build:storybook # Build Storybook for production
```
## Architecture
### Monorepo Structure
- **apps/api**: NestJS backend application
- **apps/client**: Angular frontend application
- **apps/client-e2e**: E2E tests for client
- **apps/ui-e2e**: E2E tests for UI components
- **libs/common**: Shared TypeScript libraries and utilities
- **libs/ui**: Angular UI component library
### Technology Stack
- **Frontend**: Angular 20 with Angular Material, Bootstrap utility classes
- **Backend**: NestJS with TypeScript
- **Database**: PostgreSQL with Prisma ORM
- **Caching**: Redis with Bull for job queues
- **Build Tool**: Nx workspace
- **Testing**: Jest for unit tests, Cypress for E2E tests
### Key Dependencies
- **Authentication**: Passport (JWT, Google OAuth, WebAuthn)
- **Data Sources**: Yahoo Finance, CoinGecko APIs for market data
- **Charts**: Chart.js with various plugins
- **Payment**: Stripe integration
- **Internationalization**: Angular i18n with multiple language support
### Database Schema
The Prisma schema defines models for:
- User management and access control
- Account and portfolio tracking
- Trading activities and orders
- Market data and asset information
- Platform integrations
### Development Notes
- Node.js version >=22.18.0 required
- Uses Nx generators for consistent code scaffolding
- Husky for git hooks and code quality enforcement
- Environment files: `.env.dev` for development, `.env.example` as template
- SSL certificates can be generated for localhost development
- Experimental features can be toggled via user settings
- always run the .husky pre commit hooks after code changes

4
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -188,9 +188,9 @@ export abstract class PortfolioCalculator {
if (!transactionPoints.length) {
return {
activitiesCount: 0,
dividendYieldTrailingTwelveMonths: 0,
createdAt: new Date(),
currentValueInBaseCurrency: new Big(0),
dividendYieldTrailingTwelveMonths: 0,
errors: [],
hasErrors: false,
historicalData: [],
@ -439,11 +439,11 @@ export abstract class PortfolioCalculator {
: 0;
positions.push({
dividendYieldTrailingTwelveMonths,
includeInTotalAssetValue,
timeWeightedInvestment,
timeWeightedInvestmentWithCurrencyEffect,
activitiesCount: item.activitiesCount,
dividendYieldTrailingTwelveMonths,
averagePrice: item.averagePrice,
currency: item.currency,
dataSource: item.dataSource,

2
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts

@ -231,13 +231,13 @@ describe('PortfolioCalculator', () => {
*/
expect(position).toMatchObject<TimelinePosition>({
activitiesCount: 2,
dividendYieldTrailingTwelveMonths: 0,
averagePrice: new Big(1),
currency: 'USD',
dataSource: DataSource.YAHOO,
dateOfFirstActivity: '2023-12-31',
dividend: new Big(0),
dividendInBaseCurrency: new Big(0),
dividendYieldTrailingTwelveMonths: 0,
fee: new Big(0),
feeInBaseCurrency: new Big(0),
grossPerformance: new Big(0),

3
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts

@ -289,8 +289,7 @@ describe('PortfolioCalculator', () => {
fee: new Big('19'),
quantity: new Big('1'),
symbol: 'MSFT',
tags: [],
transactionCount: 5
tags: []
}
],
totalFeesWithCurrencyEffect: new Big('19'),

2
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts

@ -125,6 +125,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
return {
currentValueInBaseCurrency,
dividendYieldTrailingTwelveMonths,
hasErrors,
positions,
totalFeesWithCurrencyEffect,
@ -134,7 +135,6 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
activitiesCount: this.activities.filter(({ type }) => {
return ['BUY', 'SELL'].includes(type);
}).length,
dividendYieldTrailingTwelveMonths,
createdAt: new Date(),
errors: [],
historicalData: [],

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

@ -1861,8 +1861,8 @@ export class PortfolioService {
}
const {
dividendYieldTrailingTwelveMonths,
currentValueInBaseCurrency,
dividendYieldTrailingTwelveMonths,
totalInvestment
} = await portfolioCalculator.getSnapshot();
@ -1962,11 +1962,11 @@ export class PortfolioService {
})?.toNumber();
return {
dividendYieldTrailingTwelveMonths,
annualizedPerformancePercent,
annualizedPerformancePercentWithCurrencyEffect,
cash,
dateOfFirstActivity,
dividendYieldTrailingTwelveMonths,
excludedAccountsAndActivities,
netPerformance,
netPerformancePercentage,

2
libs/common/src/lib/interfaces/portfolio-summary.interface.ts

@ -3,13 +3,13 @@ import { PortfolioPerformance } from './portfolio-performance.interface';
export interface PortfolioSummary extends PortfolioPerformance {
activityCount: number;
dividendYieldTrailingTwelveMonths: number;
annualizedPerformancePercent: number;
annualizedPerformancePercentWithCurrencyEffect: number;
cash: number;
committedFunds: number;
dateOfFirstActivity: Date;
dividendInBaseCurrency: number;
dividendYieldTrailingTwelveMonths: number;
emergencyFund: {
assets: number;
cash: number;

3
libs/common/src/lib/models/portfolio-snapshot.ts

@ -10,7 +10,6 @@ import { Transform, Type } from 'class-transformer';
export class PortfolioSnapshot {
activitiesCount: number;
dividendYieldTrailingTwelveMonths: number;
createdAt: Date;
@ -18,6 +17,8 @@ export class PortfolioSnapshot {
@Type(() => Big)
currentValueInBaseCurrency: Big;
dividendYieldTrailingTwelveMonths: number;
errors: AssetProfileIdentifier[];
hasErrors: boolean;

3
libs/common/src/lib/models/timeline-position.ts

@ -10,7 +10,6 @@ import { Transform, Type } from 'class-transformer';
export class TimelinePosition {
activitiesCount: number;
dividendYieldTrailingTwelveMonths: number;
@Transform(transformToBig, { toClassOnly: true })
@Type(() => Big)
@ -28,6 +27,8 @@ export class TimelinePosition {
@Type(() => Big)
dividendInBaseCurrency: Big;
dividendYieldTrailingTwelveMonths: number;
@Transform(transformToBig, { toClassOnly: true })
@Type(() => Big)
fee: Big;

Loading…
Cancel
Save