Files
splitt-the-bill/server/api/pots/[slug]/expenses.post.ts
T
anbraten cbe1b42f6e
tinyedge/deploy Deployed by TinyEdge
🐛 add env to useDb and apply prettier
2026-08-07 13:28:26 +02:00

63 lines
1.8 KiB
TypeScript

import { useDb } from '~~/server/database/client';
import { expenseParticipants, expenses } from '~~/server/database/schema';
export default defineEventHandler(async (event) => {
const slug = getRouterParam(event, 'slug')!;
await getPotOrThrow(slug);
const body = await readBody(event);
const description =
typeof body?.description === 'string' ? body.description.trim() : '';
const amountCents = Number(body?.amountCents);
const payerId = Number(body?.payerId);
const participantIds: number[] = Array.isArray(body?.participantIds)
? body.participantIds.map(Number)
: [];
if (!description) {
throw createError({
statusCode: 400,
statusMessage: 'description is required',
});
}
if (!Number.isInteger(amountCents) || amountCents <= 0) {
throw createError({
statusCode: 400,
statusMessage: 'amountCents must be a positive integer',
});
}
if (participantIds.length === 0) {
throw createError({
statusCode: 400,
statusMessage: 'at least one participant must be selected',
});
}
const potParticipants = await getParticipants(slug);
const validIds = new Set(potParticipants.map((p) => p.id));
if (
!validIds.has(payerId) ||
participantIds.some((id) => !validIds.has(id))
) {
throw createError({
statusCode: 400,
statusMessage:
'payerId and participantIds must reference participants of this Pot',
});
}
const db = useDb(event);
const [expense] = await db
.insert(expenses)
.values({ potSlug: slug, description, amountCents, payerId })
.returning();
await db.insert(expenseParticipants).values(
participantIds.map((participantId) => ({
expenseId: expense!.id,
participantId,
})),
);
return { ...expense, participantIds };
});