feat(dashboard): add pending/upcoming expenses table
- Backend: GET /expenses/pending-upcoming returns PENDING expenses with dueDate <= today+5 days, classified as overdue/upcoming - DashboardExpensesTable: groups by periodicExpenseId, shows summed totals with status badges, links to /expenses?periodicExpenseId=X - Expenses route accepts ?periodicExpenseId search param and pre-selects it in the filter - fix: BeloAnalysisPage DatePicker type mismatch
This commit is contained in:
@@ -10,6 +10,7 @@ import { payExpenseHandler } from "./handlers/payExpense";
|
||||
import { getMonthlyPayedTotalHandler } from "./handlers/getMonthlyPayedTotal";
|
||||
import { getMonthlyTotalsHandler } from "./handlers/getMonthlyTotals";
|
||||
import { getTotalPendingHandler } from "./handlers/getTotalPending";
|
||||
import { getPendingUpcomingExpensesHandler } from "./handlers/getPendingUpcomingExpenses";
|
||||
import { importPeriodicExpensesHandler } from "./handlers/importPeriodicExpenses";
|
||||
import { importExpensesHandler } from "./handlers/importExpenses";
|
||||
|
||||
@@ -24,6 +25,7 @@ app.post("/periodic-expenses/:id/generate-month", generateMonthlyExpenseHandler)
|
||||
|
||||
app.get("/expenses/monthly-total", getMonthlyPayedTotalHandler);
|
||||
app.get("/expenses/totals", getMonthlyTotalsHandler);
|
||||
app.get("/expenses/pending-upcoming", getPendingUpcomingExpensesHandler);
|
||||
app.get("/expenses/pending-total", getTotalPendingHandler);
|
||||
app.get("/expenses", listExpensesHandler);
|
||||
app.post("/expenses", createNonPeriodicExpenseHandler);
|
||||
|
||||
@@ -216,6 +216,27 @@ export async function getTotalPending() {
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function listPendingUpcomingExpenses() {
|
||||
const now = new Date();
|
||||
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0));
|
||||
const fiveDaysLater = new Date(today);
|
||||
fiveDaysLater.setUTCDate(fiveDaysLater.getUTCDate() + 5);
|
||||
|
||||
const data = await prisma.expense.findMany({
|
||||
where: {
|
||||
status: PaymentStatus.PENDING,
|
||||
dueDate: { lte: fiveDaysLater },
|
||||
},
|
||||
include: { periodicExpense: true },
|
||||
orderBy: { dueDate: "asc" },
|
||||
});
|
||||
|
||||
return data.map((expense) => ({
|
||||
...expense,
|
||||
dueType: expense.dueDate < today ? "overdue" as const : "upcoming" as const,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function generateExpensesForCurrentMonth() {
|
||||
const { year, month } = getCurrentYearMonthUTC();
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { Context } from "hono";
|
||||
import { listPendingUpcomingExpenses } from "../expenses.service";
|
||||
|
||||
export async function getPendingUpcomingExpensesHandler(c: Context) {
|
||||
const result = await listPendingUpcomingExpenses();
|
||||
return c.json(result);
|
||||
}
|
||||
Reference in New Issue
Block a user