Add PDF invoices/receipts with manual send, fix early-bird tier edit data loss

- Registration confirmations attach an invoice PDF (itemized breakdown,
  early-bird discount, balance due, Yoco pay-now link/QR) whenever a
  balance is outstanding; payment/donation confirmations attach a
  payment receipt PDF. Sent as an email attachment and, over WhatsApp,
  as the PDF itself with the existing message as its caption.
- Users can also (re)send either document on demand: an "Invoice"
  button on the registration detail popup, and a "Receipt" button next
  to each payment there and on the Payment history page, each opening
  an Email/WhatsApp choice popup, via two new endpoints restricted to
  the registration/payment's own owner.
- Fix: editing an event option's early-bird tiers deleted and
  recreated every tier for that option with brand-new ids, silently
  severing the appliedTierId link on all historical purchases (losing
  early-bird attribution and undercounting stock-limit usage) even for
  tiers the admin didn't touch. Tiers are now upserted by id.
- Update the "My Events" help content and the API docs index for the
  new endpoints.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 10:26:49 +02:00
co-authored by Claude Sonnet 5
parent e9cb238ce1
commit bc64069021
13 changed files with 835 additions and 82 deletions
+7 -1
View File
@@ -1,5 +1,5 @@
import React from "react";
import { Calendar, Ticket, CreditCard, HandHeart, Printer, CheckCircle2, ClipboardList, Clock, SquarePen, History, CheckSquare, Receipt } from "lucide-react";
import { Calendar, Ticket, CreditCard, HandHeart, Printer, CheckCircle2, ClipboardList, Clock, SquarePen, History, CheckSquare, Receipt, FileText } from "lucide-react";
import { GuideItem } from "@/components/shared/GuideItem";
import type { HelpContent } from "./types";
@@ -33,6 +33,9 @@ export const dashboardUserHelpContent: HelpContent = {
<GuideItem icon={SquarePen} title="Editing or cancelling" tone="violet">
Tap a registration to change quantities or options, pay what&apos;s outstanding, or cancel it entirely.
</GuideItem>
<GuideItem icon={FileText} title="Invoice" tone="rose">
The Invoice button sends a PDF breakdown of the registration itemized cost, any early-bird discount, and what&apos;s still owing (or &quot;Paid in full&quot;) to your email or WhatsApp, whichever you pick.
</GuideItem>
<GuideItem icon={History} title="Show past events" tone="gray">
Registrations page defaults to upcoming events only tick &quot;Show past events&quot; at the top to bring back ones that have already happened.
</GuideItem>
@@ -72,6 +75,9 @@ export const dashboardUserHelpContent: HelpContent = {
<GuideItem icon={Receipt} title="Payment history" tone="green">
The Payment history page lists every payment you&apos;ve made across all your registrations, past and present.
</GuideItem>
<GuideItem icon={Receipt} title="Receipts" tone="amber">
Every payment in a registration&apos;s Payments list, or on the Payment history page has its own Receipt button. Pick email or WhatsApp to get a PDF receipt for that specific payment.
</GuideItem>
<GuideItem icon={HandHeart} title="Donations" tone="rose">
A donation isn&apos;t tied to any one registration make one any time to support an event or the ministry directly. It can later be used to help cover an outstanding balance.
</GuideItem>