fix:manage edit for extra bezoekers payments

This commit is contained in:
2026-03-03 14:28:59 +01:00
parent 0a1d1db9ec
commit e6f52e6a73
6 changed files with 338 additions and 134 deletions

View File

@@ -172,11 +172,28 @@ export const appRouter = {
.handler(async ({ input }) => {
const row = await getActiveRegistration(input.token);
// If already paid and switching to a watcher with fewer guests, we
// still allow the update — payment adjustments are handled manually.
const isPerformer = input.registrationType === "performer";
const guests = isPerformer ? [] : (input.guests ?? []);
// Detect whether an already-paid watcher is adding extra guests so we
// can charge them the delta instead of the full amount.
const isPaid = row.paymentStatus === "paid";
const oldGuestCount = isPerformer
? 0
: parseGuestsJson(row.guests).length;
const newGuestCount = guests.length;
const extraGuests =
!isPerformer && isPaid ? newGuestCount - oldGuestCount : 0;
// Determine the new paymentStatus and paymentAmount (delta in cents).
// Only flag extra_payment_pending when the watcher genuinely owes more.
const newPaymentStatus =
isPaid && extraGuests > 0 ? "extra_payment_pending" : row.paymentStatus;
const newPaymentAmount =
newPaymentStatus === "extra_payment_pending"
? extraGuests * 2 * 100 // €2 per extra guest, in cents
: row.paymentAmount;
await db
.update(registration)
.set({
@@ -191,6 +208,8 @@ export const appRouter = {
drinkCardValue: isPerformer ? 0 : drinkCardEuros(guests.length),
guests: guests.length > 0 ? JSON.stringify(guests) : null,
extraQuestions: input.extraQuestions || null,
paymentStatus: newPaymentStatus,
paymentAmount: newPaymentAmount,
})
.where(eq(registration.managementToken, input.token));
@@ -202,9 +221,6 @@ export const appRouter = {
artForm: input.artForm,
}).catch((err) => console.error("Failed to send update email:", err));
// Satisfy the linter — row is used to confirm the record existed.
void row;
return { success: true };
}),
@@ -540,11 +556,27 @@ export const appRouter = {
if (!row) throw new Error("Inschrijving niet gevonden");
if (row.paymentStatus === "paid")
throw new Error("Betaling is al voltooid");
if (
row.paymentStatus !== "pending" &&
row.paymentStatus !== "extra_payment_pending"
)
throw new Error("Onverwachte betalingsstatus");
if (row.registrationType === "performer")
throw new Error("Artiesten hoeven niet te betalen");
const guests = parseGuestsJson(row.guests);
const amountInCents = drinkCardCents(guests.length);
// For an extra_payment_pending registration, charge only the delta
// (stored in paymentAmount in cents). For a fresh pending registration
// charge the full drink card price.
const isExtraPayment = row.paymentStatus === "extra_payment_pending";
const amountInCents = isExtraPayment
? (row.paymentAmount ?? 0)
: drinkCardCents(guests.length);
const productDescription = isExtraPayment
? `Extra bijdrage voor ${row.paymentAmount != null ? row.paymentAmount / 200 : 0} extra gast(en)`
: `Toegangskaart voor ${1 + guests.length} perso(o)n(en)`;
const response = await fetch(
"https://api.lemonsqueezy.com/v1/checkouts",
@@ -562,7 +594,7 @@ export const appRouter = {
custom_price: amountInCents,
product_options: {
name: "Kunstenkamp Evenement",
description: `Toegangskaart voor ${1 + guests.length} perso(o)n(en)`,
description: productDescription,
redirect_url: `${env.CORS_ORIGIN}/manage/${input.token}`,
},
checkout_data: {