fix: fix no budget session in rebalance get route
All checks were successful
Deploy / deploy (push) Successful in 1m28s
Security Tests / security-non-db (push) Successful in 19s
Security Tests / security-db (push) Successful in 25s

This commit is contained in:
2026-03-11 21:44:19 -05:00
parent 90131d61fc
commit 51510f1685

View File

@@ -3395,6 +3395,27 @@ async function getLatestBudgetSession(app: any, userId: string) {
});
}
async function ensureBudgetSession(app: any, userId: string, fallbackAvailableCents = 0) {
const existing = await getLatestBudgetSession(app, userId);
if (existing) return existing;
const now = new Date();
const start = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1, 0, 0, 0, 0));
const end = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1, 0, 0, 0, 0));
return app.prisma.budgetSession.create({
data: {
userId,
periodStart: start,
periodEnd: end,
totalBudgetCents: BigInt(Math.max(0, fallbackAvailableCents)),
allocatedCents: 0n,
fundedCents: 0n,
availableCents: BigInt(Math.max(0, fallbackAvailableCents)),
},
});
}
app.post("/variable-categories", mutationRateLimit, async (req, reply) => {
const parsed = CatBody.safeParse(req.body);
if (!parsed.success) {
@@ -3527,14 +3548,13 @@ app.post("/variable-categories/rebalance", mutationRateLimit, async (req, reply)
app.get("/variable-categories/manual-rebalance", async (req, reply) => {
const userId = req.userId;
const session = await getLatestBudgetSession(app, userId);
if (!session) return reply.code(400).send({ ok: false, code: "NO_BUDGET_SESSION" });
const cats = await app.prisma.variableCategory.findMany({
where: { userId },
orderBy: [{ priority: "asc" }, { name: "asc" }],
select: { id: true, name: true, percent: true, isSavings: true, balanceCents: true },
});
const totalBalance = cats.reduce((s, c) => s + Number(c.balanceCents ?? 0n), 0);
const session = await ensureBudgetSession(app, userId, totalBalance);
return reply.send({
ok: true,
@@ -3550,10 +3570,6 @@ app.post("/variable-categories/manual-rebalance", async (req, reply) => {
return reply.code(400).send({ ok: false, code: "INVALID_BODY" });
}
const session = await getLatestBudgetSession(app, userId);
if (!session) return reply.code(400).send({ ok: false, code: "NO_BUDGET_SESSION" });
const availableCents = Number(session.availableCents ?? 0n);
const cats = await app.prisma.variableCategory.findMany({
where: { userId },
orderBy: [{ priority: "asc" }, { name: "asc" }],
@@ -3561,6 +3577,10 @@ app.post("/variable-categories/manual-rebalance", async (req, reply) => {
});
if (cats.length === 0) return reply.code(400).send({ ok: false, code: "NO_CATEGORIES" });
const totalBalance = cats.reduce((s, c) => s + Number(c.balanceCents ?? 0n), 0);
const session = await ensureBudgetSession(app, userId, totalBalance);
const availableCents = Number(session.availableCents ?? 0n);
const targetMap = new Map<string, number>();
for (const t of parsed.data.targets) {
if (targetMap.has(t.id)) return reply.code(400).send({ ok: false, code: "DUPLICATE_ID" });