- Introduced a comprehensive backend API using TypeScript, Fastify, and PostgreSQL. - Added essential files including architecture documentation, environment configuration, and Docker setup. - Implemented RESTful routes for managing assets, liabilities, clients, invoices, and cashflow. - Established a robust database schema with Prisma for data management. - Integrated middleware for authentication and error handling. - Created service and repository layers to adhere to SOLID principles and clean architecture. - Included example environment variables for development, staging, and production setups.
113 lines
2.9 KiB
TypeScript
113 lines
2.9 KiB
TypeScript
import {NetWorthSnapshot, Prisma} from '@prisma/client';
|
|
import {DatabaseConnection} from '../config/database';
|
|
import {IUserScopedRepository} from './interfaces/IRepository';
|
|
|
|
const prisma = DatabaseConnection.getInstance();
|
|
|
|
/**
|
|
* Repository for NetWorthSnapshot data access
|
|
* Implements Single Responsibility Principle - handles only database operations
|
|
*/
|
|
export class NetWorthSnapshotRepository implements IUserScopedRepository<NetWorthSnapshot> {
|
|
async findById(id: string): Promise<NetWorthSnapshot | null> {
|
|
return prisma.netWorthSnapshot.findUnique({
|
|
where: {id},
|
|
});
|
|
}
|
|
|
|
async findAllByUser(userId: string): Promise<NetWorthSnapshot[]> {
|
|
return prisma.netWorthSnapshot.findMany({
|
|
where: {userId},
|
|
orderBy: {date: 'desc'},
|
|
});
|
|
}
|
|
|
|
async create(data: Prisma.NetWorthSnapshotCreateInput): Promise<NetWorthSnapshot> {
|
|
return prisma.netWorthSnapshot.create({
|
|
data,
|
|
});
|
|
}
|
|
|
|
async update(id: string, data: Prisma.NetWorthSnapshotUpdateInput): Promise<NetWorthSnapshot> {
|
|
return prisma.netWorthSnapshot.update({
|
|
where: {id},
|
|
data,
|
|
});
|
|
}
|
|
|
|
async delete(id: string): Promise<void> {
|
|
await prisma.netWorthSnapshot.delete({
|
|
where: {id},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get the latest snapshot for a user
|
|
*/
|
|
async getLatest(userId: string): Promise<NetWorthSnapshot | null> {
|
|
return prisma.netWorthSnapshot.findFirst({
|
|
where: {userId},
|
|
orderBy: {date: 'desc'},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get snapshots within a date range
|
|
*/
|
|
async getByDateRange(userId: string, startDate: Date, endDate: Date): Promise<NetWorthSnapshot[]> {
|
|
return prisma.netWorthSnapshot.findMany({
|
|
where: {
|
|
userId,
|
|
date: {
|
|
gte: startDate,
|
|
lte: endDate,
|
|
},
|
|
},
|
|
orderBy: {date: 'asc'},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Check if a snapshot exists for a specific date
|
|
*/
|
|
async existsForDate(userId: string, date: Date): Promise<boolean> {
|
|
const count = await prisma.netWorthSnapshot.count({
|
|
where: {
|
|
userId,
|
|
date,
|
|
},
|
|
});
|
|
|
|
return count > 0;
|
|
}
|
|
|
|
/**
|
|
* Get growth over time (percentage change between snapshots)
|
|
*/
|
|
async getGrowthStats(userId: string, limit: number = 12): Promise<any[]> {
|
|
const snapshots = await prisma.netWorthSnapshot.findMany({
|
|
where: {userId},
|
|
orderBy: {date: 'desc'},
|
|
take: limit,
|
|
});
|
|
|
|
const stats = [];
|
|
for (let i = 0; i < snapshots.length - 1; i++) {
|
|
const current = snapshots[i];
|
|
const previous = snapshots[i + 1];
|
|
const growthAmount = current.netWorth - previous.netWorth;
|
|
const growthPercent =
|
|
previous.netWorth !== 0 ? (growthAmount / previous.netWorth) * 100 : 0;
|
|
|
|
stats.push({
|
|
date: current.date,
|
|
netWorth: current.netWorth,
|
|
growthAmount,
|
|
growthPercent: parseFloat(growthPercent.toFixed(2)),
|
|
});
|
|
}
|
|
|
|
return stats;
|
|
}
|
|
}
|