import { prisma } from "./db.server"; import type { Expense } from "@prisma/client"; import type { CreateExpenseData, UpdateExpenseData, FinancialSearchParams } from "~/types/database"; // Get all expenses with search and pagination export async function getExpenses( searchQuery?: string, page: number = 1, limit: number = 10, category?: string, dateFrom?: Date, dateTo?: Date ): Promise<{ expenses: Expense[]; total: number; totalPages: number; }> { const offset = (page - 1) * limit; // Build where clause for search and filters const whereClause: any = {}; if (category) { whereClause.category = category; } if (dateFrom || dateTo) { whereClause.expenseDate = {}; if (dateFrom) { whereClause.expenseDate.gte = dateFrom; } if (dateTo) { whereClause.expenseDate.lte = dateTo; } } if (searchQuery) { const searchLower = searchQuery.toLowerCase(); whereClause.OR = [ { description: { contains: searchLower } }, { category: { contains: searchLower } }, ]; } const [expenses, total] = await Promise.all([ prisma.expense.findMany({ where: whereClause, orderBy: { expenseDate: 'desc' }, skip: offset, take: limit, }), prisma.expense.count({ where: whereClause }), ]); const totalPages = Math.ceil(total / limit); return { expenses, total, totalPages, }; } // Get a single expense by ID export async function getExpenseById(id: number): Promise { return prisma.expense.findUnique({ where: { id }, }); } // Create a new expense export async function createExpense(data: CreateExpenseData): Promise { return prisma.expense.create({ data: { description: data.description, category: data.category, amount: data.amount, expenseDate: data.expenseDate || new Date(), }, }); } // Update an existing expense export async function updateExpense(id: number, data: UpdateExpenseData): Promise { return prisma.expense.update({ where: { id }, data: { description: data.description, category: data.category, amount: data.amount, expenseDate: data.expenseDate, }, }); } // Delete an expense export async function deleteExpense(id: number): Promise { await prisma.expense.delete({ where: { id }, }); } // Get expense categories for dropdown export async function getExpenseCategories(): Promise { const categories = await prisma.expense.findMany({ select: { category: true }, distinct: ['category'], orderBy: { category: 'asc' }, }); return categories.map(c => c.category); } // Get expenses by category for reporting export async function getExpensesByCategory( dateFrom?: Date, dateTo?: Date ): Promise<{ category: string; total: number; count: number }[]> { const whereClause: any = {}; if (dateFrom || dateTo) { whereClause.expenseDate = {}; if (dateFrom) { whereClause.expenseDate.gte = dateFrom; } if (dateTo) { whereClause.expenseDate.lte = dateTo; } } const result = await prisma.expense.groupBy({ by: ['category'], where: whereClause, _sum: { amount: true, }, _count: { id: true, }, orderBy: { _sum: { amount: 'desc', }, }, }); return result.map(item => ({ category: item.category, total: item._sum.amount || 0, count: item._count.id, })); } // Get total expenses for a date range export async function getTotalExpenses(dateFrom?: Date, dateTo?: Date): Promise { const whereClause: any = {}; if (dateFrom || dateTo) { whereClause.expenseDate = {}; if (dateFrom) { whereClause.expenseDate.gte = dateFrom; } if (dateTo) { whereClause.expenseDate.lte = dateTo; } } const result = await prisma.expense.aggregate({ where: whereClause, _sum: { amount: true, }, }); return result._sum.amount || 0; }