🎉 init
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import { useDb } from '../../../database/client'
|
||||
import { expenseParticipants, expenses } from '../../../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()
|
||||
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 }
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { useDb } from '../../../../database/client'
|
||||
import { expenseParticipants, expenses } from '../../../../database/schema'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const slug = getRouterParam(event, 'slug')!
|
||||
const id = Number(getRouterParam(event, 'id'))
|
||||
await getPotOrThrow(slug)
|
||||
|
||||
const db = useDb()
|
||||
const [existing] = await db.select().from(expenses).where(and(eq(expenses.id, id), eq(expenses.potSlug, slug)))
|
||||
if (!existing) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Expense not found' })
|
||||
}
|
||||
|
||||
await db.delete(expenseParticipants).where(eq(expenseParticipants.expenseId, id))
|
||||
await db.delete(expenses).where(eq(expenses.id, id))
|
||||
|
||||
return { success: true }
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { useDb } from '../../../../database/client'
|
||||
import { expenseParticipants, expenses } from '../../../../database/schema'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const slug = getRouterParam(event, 'slug')!
|
||||
const id = Number(getRouterParam(event, 'id'))
|
||||
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(pid => !validIds.has(pid))) {
|
||||
throw createError({ statusCode: 400, statusMessage: 'payerId and participantIds must reference participants of this Pot' })
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
const [existing] = await db.select().from(expenses).where(and(eq(expenses.id, id), eq(expenses.potSlug, slug)))
|
||||
if (!existing) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Expense not found' })
|
||||
}
|
||||
|
||||
await db.update(expenses).set({ description, amountCents, payerId }).where(eq(expenses.id, id))
|
||||
await db.delete(expenseParticipants).where(eq(expenseParticipants.expenseId, id))
|
||||
await db.insert(expenseParticipants).values(participantIds.map(participantId => ({ expenseId: id, participantId })))
|
||||
|
||||
return { id, description, amountCents, payerId, participantIds }
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
import { useDb } from '../../../database/client'
|
||||
import { participants } from '../../../database/schema'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const slug = getRouterParam(event, 'slug')!
|
||||
await getPotOrThrow(slug)
|
||||
|
||||
const body = await readBody(event)
|
||||
const name = typeof body?.name === 'string' ? body.name.trim() : ''
|
||||
if (!name) {
|
||||
throw createError({ statusCode: 400, statusMessage: 'name is required' })
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
const [participant] = await db.insert(participants).values({ potSlug: slug, name }).returning()
|
||||
return participant
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { isValidPaymentLink } from '../../../../../shared/utils/paymentLink'
|
||||
import { useDb } from '../../../../database/client'
|
||||
import { participants } from '../../../../database/schema'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const slug = getRouterParam(event, 'slug')!
|
||||
const id = Number(getRouterParam(event, 'id'))
|
||||
await getPotOrThrow(slug)
|
||||
|
||||
const body = await readBody(event)
|
||||
const paymentLink = typeof body?.paymentLink === 'string' ? body.paymentLink.trim() : ''
|
||||
if (paymentLink && !isValidPaymentLink(paymentLink)) {
|
||||
throw createError({ statusCode: 400, statusMessage: 'paymentLink must be a valid http(s) URL' })
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
const [existing] = await db.select().from(participants).where(and(eq(participants.id, id), eq(participants.potSlug, slug)))
|
||||
if (!existing) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Participant not found' })
|
||||
}
|
||||
|
||||
const [updated] = await db.update(participants)
|
||||
.set({ paymentLink: paymentLink || null })
|
||||
.where(eq(participants.id, id))
|
||||
.returning()
|
||||
|
||||
return updated
|
||||
})
|
||||
@@ -0,0 +1,33 @@
|
||||
import { useDb } from '../../../database/client'
|
||||
import { expenseParticipants, expenses } from '../../../database/schema'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const slug = getRouterParam(event, 'slug')!
|
||||
await getPotOrThrow(slug)
|
||||
|
||||
const body = await readBody(event)
|
||||
const fromId = Number(body?.fromId)
|
||||
const toId = Number(body?.toId)
|
||||
const amountCents = Number(body?.amountCents)
|
||||
|
||||
if (!Number.isInteger(amountCents) || amountCents <= 0) {
|
||||
throw createError({ statusCode: 400, statusMessage: 'amountCents must be a positive integer' })
|
||||
}
|
||||
if (fromId === toId) {
|
||||
throw createError({ statusCode: 400, statusMessage: 'fromId and toId must differ' })
|
||||
}
|
||||
|
||||
const potParticipants = await getParticipants(slug)
|
||||
const validIds = new Set(potParticipants.map(p => p.id))
|
||||
if (!validIds.has(fromId) || !validIds.has(toId)) {
|
||||
throw createError({ statusCode: 400, statusMessage: 'fromId and toId must reference participants of this Pot' })
|
||||
}
|
||||
|
||||
const db = useDb()
|
||||
const [payment] = await db.insert(expenses)
|
||||
.values({ potSlug: slug, type: 'payment', description: 'Settlement', amountCents, payerId: fromId })
|
||||
.returning()
|
||||
await db.insert(expenseParticipants).values({ expenseId: payment.id, participantId: toId })
|
||||
|
||||
return { ...payment, participantIds: [toId] }
|
||||
})
|
||||
Reference in New Issue
Block a user