Files
SkyMoney/api/src/services/budget-session.ts
Ricearoni1245 ba549f6c84
All checks were successful
Deploy / deploy (push) Successful in 1m28s
Security Tests / security-non-db (push) Successful in 20s
Security Tests / security-db (push) Successful in 25s
added udner construction for file compaction, planning for unbloating
2026-03-15 14:44:47 -05:00

71 lines
1.8 KiB
TypeScript

import type { Prisma, PrismaClient } from "@prisma/client";
type BudgetSessionAccessor =
| Pick<PrismaClient, "budgetSession">
| Pick<Prisma.TransactionClient, "budgetSession">;
function normalizeAvailableCents(value: number): bigint {
if (!Number.isFinite(value)) return 0n;
return BigInt(Math.max(0, Math.trunc(value)));
}
export async function getLatestBudgetSession(
db: BudgetSessionAccessor,
userId: string
) {
return db.budgetSession.findFirst({
where: { userId },
orderBy: { periodStart: "desc" },
});
}
export async function ensureBudgetSession(
db: BudgetSessionAccessor,
userId: string,
fallbackAvailableCents = 0,
now = new Date()
) {
const existing = await getLatestBudgetSession(db, userId);
if (existing) return existing;
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)
);
const normalizedAvailable = normalizeAvailableCents(fallbackAvailableCents);
return db.budgetSession.create({
data: {
userId,
periodStart: start,
periodEnd: end,
totalBudgetCents: normalizedAvailable,
allocatedCents: 0n,
fundedCents: 0n,
availableCents: normalizedAvailable,
},
});
}
export async function ensureBudgetSessionAvailableSynced(
db: BudgetSessionAccessor,
userId: string,
availableCents: number
) {
const normalizedAvailable = normalizeAvailableCents(availableCents);
const session = await ensureBudgetSession(
db,
userId,
Number(normalizedAvailable)
);
if ((session.availableCents ?? 0n) === normalizedAvailable) return session;
return db.budgetSession.update({
where: { id: session.id },
data: { availableCents: normalizedAvailable },
});
}