diff --git a/apps/backend/src/modules/portfolio/portfolio.service.ts b/apps/backend/src/modules/portfolio/portfolio.service.ts index fd1dcd1..c58ef7d 100644 --- a/apps/backend/src/modules/portfolio/portfolio.service.ts +++ b/apps/backend/src/modules/portfolio/portfolio.service.ts @@ -60,10 +60,55 @@ export class PortfolioService { } async findAll(userId: number) { - return this.prisma.portfolio.findMany({ + const portfolios = await this.prisma.portfolio.findMany({ where: { userId }, + include: { positions: true }, orderBy: { updatedAt: 'desc' }, }); + + const allPositions = portfolios.flatMap((p) => p.positions); + if (allPositions.length === 0) { + return portfolios.map((p) => ({ + id: p.id, + name: p.name, + description: p.description, + currency: p.currency, + createdAt: p.createdAt.toISOString(), + updatedAt: p.updatedAt.toISOString(), + totalValue: 0, + positionCount: 0, + shareCount: 0, + bondCount: 0, + })); + } + + const enrichedPositions = await this.enrichPositions(allPositions); + + const posByPortfolioId = new Map(); + for (let i = 0; i < enrichedPositions.length; i++) { + const pfId = allPositions[i].portfolioId; + if (!posByPortfolioId.has(pfId)) { + posByPortfolioId.set(pfId, []); + } + posByPortfolioId.get(pfId)!.push(enrichedPositions[i]); + } + + return portfolios.map((p) => { + const positions = posByPortfolioId.get(p.id) ?? []; + const totalValue = positions.reduce((sum, pos) => sum + (pos.currentValue ?? 0), 0); + return { + id: p.id, + name: p.name, + description: p.description, + currency: p.currency, + createdAt: p.createdAt.toISOString(), + updatedAt: p.updatedAt.toISOString(), + totalValue: Math.round(totalValue * 100) / 100, + positionCount: positions.length, + shareCount: positions.filter((pos) => pos.type === 'share').length, + bondCount: positions.filter((pos) => pos.type === 'bond').length, + }; + }); } async findOne(userId: number, id: number) {