Preview: expenseController.js
Size: 8.50 KB
/home/byroehnu/easepay.easetack.com/controllers/expenseController.js
const { prisma } = require('../config/prisma');
const getExpenses = async (req, res) => {
try {
const { page = 1, limit = 10, startDate, endDate, category } = req.query;
const offset = (parseInt(page) - 1) * parseInt(limit);
// Build where clause
const whereClause = { userId: req.user.id };
if (startDate) {
whereClause.date = {
...whereClause.date,
gte: new Date(startDate)
};
}
if (endDate) {
whereClause.date = {
...whereClause.date,
lte: new Date(endDate)
};
}
if (category) {
whereClause.category = category;
}
// Get expenses with pagination
const expenses = await prisma.expense.findMany({
where: whereClause,
orderBy: { date: 'desc' },
skip: offset,
take: parseInt(limit),
include: {
business: {
select: {
name: true
}
}
}
});
// Get total count for pagination
const total = await prisma.expense.count({
where: whereClause
});
const totalPages = Math.ceil(total / parseInt(limit));
res.status(200).json({
success: true,
expenses: expenses,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
totalPages
}
});
} catch (error) {
console.error('Get expenses error:', error);
res.status(500).json({
success: false,
message: 'Failed to get expenses'
});
}
};
const getExpenseById = async (req, res) => {
try {
const { id } = req.params;
const expense = await prisma.expense.findFirst({
where: {
id: parseInt(id),
userId: req.user.id
},
include: {
business: {
select: {
businessName: true
}
}
}
});
if (!expense) {
return res.status(404).json({
success: false,
message: 'Expense not found'
});
}
res.status(200).json({
success: true,
expense: expense
});
} catch (error) {
console.error('Get expense by ID error:', error);
res.status(500).json({
success: false,
message: 'Failed to get expense'
});
}
};
const createExpense = async (req, res) => {
try {
const {
description,
amount,
category,
paymentMethod,
expenseDate,
businessId
} = req.body;
// Validation
if (!description || !amount || !category) {
return res.status(400).json({
success: false,
message: 'Please provide description, amount, and category'
});
}
// If businessId provided, verify it belongs to the user
if (businessId) {
const business = await prisma.business.findFirst({
where: {
id: businessId,
userId: req.user.id
}
});
if (!business) {
return res.status(400).json({
success: false,
message: 'Invalid business ID'
});
}
}
const newExpense = await prisma.expense.create({
data: {
userId: req.user.id,
businessId: businessId || null,
description,
amount: parseFloat(amount),
category,
paymentMethod: paymentMethod || 'CASH',
date: expenseDate ? new Date(expenseDate) : new Date()
}
});
res.status(201).json({
success: true,
message: 'Expense created successfully',
expense: newExpense
});
} catch (error) {
console.error('Create expense error:', error);
res.status(500).json({
success: false,
message: 'Failed to create expense'
});
}
};
const updateExpense = async (req, res) => {
try {
const { id } = req.params;
const {
description,
amount,
category,
paymentMethod,
expenseDate,
businessId
} = req.body;
// Check if expense exists and belongs to user
const existingExpense = await prisma.expense.findFirst({
where: {
id: parseInt(id),
userId: req.user.id
}
});
if (!existingExpense) {
return res.status(404).json({
success: false,
message: 'Expense not found'
});
}
// If businessId provided, verify it belongs to the user
if (businessId) {
const business = await prisma.business.findFirst({
where: {
id: businessId,
userId: req.user.id
}
});
if (!business) {
return res.status(400).json({
success: false,
message: 'Invalid business ID'
});
}
}
// Build update data with only provided fields
const updateData = {};
if (description !== undefined) updateData.description = description;
if (amount !== undefined) updateData.amount = parseFloat(amount);
if (category !== undefined) updateData.category = category;
if (paymentMethod !== undefined) updateData.paymentMethod = paymentMethod;
if (expenseDate !== undefined) updateData.date = new Date(expenseDate);
if (businessId !== undefined) updateData.businessId = businessId;
const updatedExpense = await prisma.expense.update({
where: { id: parseInt(id) },
data: updateData
});
res.status(200).json({
success: true,
message: 'Expense updated successfully',
expense: updatedExpense
});
} catch (error) {
console.error('Update expense error:', error);
res.status(500).json({
success: false,
message: 'Failed to update expense'
});
}
};
const deleteExpense = async (req, res) => {
try {
const { id } = req.params;
const existingExpense = await prisma.expense.findFirst({
where: {
id: parseInt(id),
userId: req.user.id
}
});
if (!existingExpense) {
return res.status(404).json({
success: false,
message: 'Expense not found'
});
}
await prisma.expense.delete({
where: { id: parseInt(id) }
});
res.status(200).json({
success: true,
message: 'Expense deleted successfully'
});
} catch (error) {
console.error('Delete expense error:', error);
res.status(500).json({
success: false,
message: 'Failed to delete expense'
});
}
};
const getExpenseAnalytics = async (req, res) => {
try {
// Get total expenses
const totalExpenses = await prisma.expense.aggregate({
where: { userId: req.user.id },
_sum: { amount: true },
_count: { id: true }
});
// Get expenses by category
const expensesByCategory = await prisma.expense.groupBy({
by: ['category'],
where: { userId: req.user.id },
_sum: { amount: true },
_count: { id: true }
});
// Get monthly expenses for current year
const currentYear = new Date().getFullYear();
const monthlyExpenses = await prisma.expense.groupBy({
by: ['date'],
where: {
userId: req.user.id,
date: {
gte: new Date(`${currentYear}-01-01`),
lte: new Date(`${currentYear}-12-31`)
}
},
_sum: { amount: true },
_count: { id: true }
});
// Process monthly data
const monthlyData = Array.from({ length: 12 }, (_, i) => ({
month: i + 1,
expenses: 0,
count: 0
}));
monthlyExpenses.forEach(expense => {
const month = expense.date.getMonth();
if (monthlyData[month]) {
monthlyData[month].expenses += Number(expense._sum.amount) || 0;
monthlyData[month].count += expense._count.id;
}
});
const analytics = {
totalExpenses: Number(totalExpenses._sum.amount) || 0,
totalCount: totalExpenses._count.id || 0,
expensesByCategory: expensesByCategory.map(cat => ({
category: cat.category,
amount: Number(cat._sum.amount) || 0,
count: cat._count.id
})),
monthlyExpenses: monthlyData
};
res.status(200).json({
success: true,
data: analytics
});
} catch (error) {
console.error('Error fetching expense analytics:', error);
res.status(500).json({
success: false,
message: 'Server error'
});
}
};
module.exports = {
getExpenses,
getExpenseById,
createExpense,
updateExpense,
deleteExpense,
getExpenseAnalytics
};
Directory Contents
Dirs: 1 × Files: 17