Centralize seat capacity accounting and the payment provider registry.
Replace manualProviders.ts with a paymentProviders.ts registry (automatic vs manual settlement) and move all seat counting into capacity.ts as the single source of truth: only paid/checked-in tickets and pending_approval payments hold a seat, so abandoned checkouts never block sales. Admins can now knowingly approve a payment over capacity (allowOverCapacity), with the booking and admin UIs updated to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c9a600b6d6
commit
71c277045b
@@ -205,3 +205,33 @@ export function getTpagoLink(
|
||||
const key = (count <= 1 ? 'tpagoLink' : `tpagoLink${count}`) as keyof TpagoLinkConfig;
|
||||
return config[key] || config.tpagoLink || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spots left for an event, trusting the server's `availableSeats` (which uses
|
||||
* the same seat-holding formula the booking API enforces: paid + claimed
|
||||
* seats count, abandoned pending bookings don't). Falls back to deriving it
|
||||
* from the counts for older API responses.
|
||||
*/
|
||||
export function eventSpotsLeft(event: {
|
||||
capacity: number;
|
||||
bookedCount?: number;
|
||||
claimedCount?: number;
|
||||
availableSeats?: number;
|
||||
}): number {
|
||||
if (typeof event.availableSeats === 'number') {
|
||||
return Math.max(0, event.availableSeats);
|
||||
}
|
||||
return Math.max(
|
||||
0,
|
||||
(event.capacity ?? 0) - (event.bookedCount ?? 0) - (event.claimedCount ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
export function isEventSoldOut(event: {
|
||||
capacity: number;
|
||||
bookedCount?: number;
|
||||
claimedCount?: number;
|
||||
availableSeats?: number;
|
||||
}): boolean {
|
||||
return eventSpotsLeft(event) <= 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user