47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import { readBody, createError } from 'h3'
|
|
import { prisma } from '../../utils/db'
|
|
import { requireUser } from '../../utils/auth'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const user = await requireUser(event)
|
|
const body = await readBody<{
|
|
type: 'income' | 'expense'
|
|
occurredAt: string
|
|
assetId: string
|
|
categoryId: string
|
|
amount: number
|
|
title: string
|
|
memo?: string
|
|
latitude?: number | null
|
|
longitude?: number | null
|
|
}>(event)
|
|
|
|
if (!body.title?.trim() || !body.amount || body.amount < 1) {
|
|
throw createError({ statusCode: 400, statusMessage: 'Invalid transaction' })
|
|
}
|
|
|
|
const [asset, category] = await Promise.all([
|
|
prisma.asset.findFirst({ where: { id: body.assetId, userId: user.id, active: true } }),
|
|
prisma.category.findFirst({ where: { id: body.categoryId, userId: user.id, type: body.type, active: true } })
|
|
])
|
|
|
|
if (!asset || !category) {
|
|
throw createError({ statusCode: 400, statusMessage: 'Invalid asset or category' })
|
|
}
|
|
|
|
return prisma.transaction.create({
|
|
data: {
|
|
userId: user.id,
|
|
type: body.type,
|
|
occurredAt: new Date(body.occurredAt),
|
|
assetId: body.assetId,
|
|
categoryId: body.categoryId,
|
|
amount: Number(body.amount),
|
|
title: body.title.trim(),
|
|
memo: body.memo?.trim().slice(0, 60) || null,
|
|
latitude: body.latitude ?? null,
|
|
longitude: body.longitude ?? null
|
|
}
|
|
})
|
|
})
|