import type { Account, Transaction } from '../types.js'; import { prisma } from './prisma'; // Define the enums ourselves since Prisma isn't exporting them export enum AccountType { CHECKING = 'CHECKING', SAVINGS = 'SAVINGS', CREDIT_CARD = 'CREDIT_CARD', INVESTMENT = 'INVESTMENT', OTHER = 'OTHER', } export enum AccountStatus { ACTIVE = 'ACTIVE', CLOSED = 'CLOSED', } export enum TransactionStatus { PENDING = 'PENDING', CLEARED = 'CLEARED', } export enum TransactionType { DEPOSIT = 'DEPOSIT', WITHDRAWAL = 'WITHDRAWAL', TRANSFER = 'TRANSFER', UNSPECIFIED = 'UNSPECIFIED', } // Account services export const accountService = { /** * Get all accounts */ async getAll(): Promise { return prisma.account.findMany({ orderBy: { name: 'asc' }, }) as Promise; }, /** * Get account by ID */ async getById(id: string): Promise { return prisma.account.findUnique({ where: { id }, }) as Promise; }, /** * Create a new account */ async create(data: { bankName: string; accountNumber: string; name: string; type?: AccountType; status?: AccountStatus; currency?: string; balance?: number; notes?: string; }): Promise { return prisma.account.create({ data, }) as Promise; }, /** * Update an account */ async update( id: string, data: { bankName?: string; accountNumber?: string; name?: string; type?: AccountType; status?: AccountStatus; currency?: string; balance?: number; notes?: string; }, ): Promise { return prisma.account.update({ where: { id }, data, }) as Promise; }, /** * Delete an account */ async delete(id: string): Promise { return prisma.account.delete({ where: { id }, }) as Promise; }, /** * Update account balance */ async updateBalance(id: string, amount: number): Promise { const account = await prisma.account.findUnique({ where: { id }, }); if (!account) return null; return prisma.account.update({ where: { id }, data: { balance: { increment: amount, }, }, }) as Promise; }, /** * Get transactions for an account */ async getTransactions(accountId: string): Promise { return prisma.transaction.findMany({ where: { accountId }, orderBy: { date: 'desc' }, }) as Promise; }, }; // Transaction services export const transactionService = { /** * Get all transactions */ async getAll(): Promise { return prisma.transaction.findMany({ orderBy: { date: 'desc' }, }) as Promise; }, /** * Get transactions by account ID */ async getByAccountId(accountId: string): Promise { return prisma.transaction.findMany({ where: { accountId }, orderBy: { date: 'desc' }, }) as Promise; }, /** * Get transaction by ID */ async getById(id: string): Promise { return prisma.transaction.findUnique({ where: { id }, }) as Promise; }, /** * Create a new transaction and update account balance */ async create(data: { accountId: string; date: Date; description: string; amount: number; category?: string; status?: TransactionStatus; type?: TransactionType; notes?: string; tags?: string; }): Promise { // Use a transaction to ensure data consistency return prisma.$transaction(async (tx) => { // Create the transaction const transaction = await tx.transaction.create({ data, }); // Update the account balance await tx.account.update({ where: { id: data.accountId }, data: { balance: { increment: data.amount, }, }, }); return transaction as Transaction; }); }, /** * Update a transaction and adjust account balance */ async update( id: string, data: { accountId?: string; date?: Date; description?: string; amount?: number; category?: string; status?: TransactionStatus; type?: TransactionType; notes?: string; tags?: string; }, ): Promise { // If amount is changing, we need to adjust the account balance if (typeof data.amount !== 'undefined') { return prisma.$transaction(async (tx) => { // Get the current transaction to calculate difference const currentTxn = await tx.transaction.findUnique({ where: { id }, }); if (!currentTxn) return null; // Amount is guaranteed to be defined at this point since we checked above const amount = data.amount as number; // Use type assertion instead of non-null assertion const amountDifference = amount - Number(currentTxn.amount); // Update transaction const updatedTxn = await tx.transaction.update({ where: { id }, data, }); // Update account balance await tx.account.update({ where: { id: data.accountId || currentTxn.accountId }, data: { balance: { increment: amountDifference, }, }, }); return updatedTxn as Transaction; }); } // If amount isn't changing, just update the transaction return prisma.transaction.update({ where: { id }, data, }) as Promise; }, /** * Delete a transaction and adjust account balance */ async delete(id: string): Promise { return prisma.$transaction(async (tx) => { // Get transaction before deleting const transaction = await tx.transaction.findUnique({ where: { id }, }); if (!transaction) return null; // Delete the transaction const deletedTxn = await tx.transaction.delete({ where: { id }, }); // Adjust the account balance (reverse the transaction amount) await tx.account.update({ where: { id: transaction.accountId }, data: { balance: { decrement: Number(transaction.amount), }, }, }); return deletedTxn as Transaction; }); }, };