Fix event capacity: no negative availability, sold-out enforcement, admin override
- Backend: use calculateAvailableSeats so availableSeats is never negative - Backend: reject public booking when confirmed >= capacity; admin create/manual bypass capacity - Frontend: spotsLeft = max(0, capacity - bookedCount), isSoldOut when bookedCount >= capacity - Frontend: sold-out redirect on booking page, cap quantity by spotsLeft, never show negative Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { z } from 'zod';
|
||||
import { db, dbGet, dbAll, events, tickets, payments, eventPaymentOverrides, emailLogs, invoices, siteSettings } from '../db/index.js';
|
||||
import { eq, desc, and, gte, sql } from 'drizzle-orm';
|
||||
import { requireAuth, getAuthUser } from '../lib/auth.js';
|
||||
import { generateId, getNow, convertBooleansForDb, toDbDate } from '../lib/utils.js';
|
||||
import { generateId, getNow, convertBooleansForDb, toDbDate, calculateAvailableSeats } from '../lib/utils.js';
|
||||
|
||||
interface UserContext {
|
||||
id: string;
|
||||
@@ -151,10 +151,11 @@ eventsRouter.get('/', async (c) => {
|
||||
);
|
||||
|
||||
const normalized = normalizeEvent(event);
|
||||
const bookedCount = ticketCount?.count || 0;
|
||||
return {
|
||||
...normalized,
|
||||
bookedCount: ticketCount?.count || 0,
|
||||
availableSeats: normalized.capacity - (ticketCount?.count || 0),
|
||||
bookedCount,
|
||||
availableSeats: calculateAvailableSeats(normalized.capacity, bookedCount),
|
||||
};
|
||||
})
|
||||
);
|
||||
@@ -189,11 +190,12 @@ eventsRouter.get('/:id', async (c) => {
|
||||
);
|
||||
|
||||
const normalized = normalizeEvent(event);
|
||||
const bookedCount = ticketCount?.count || 0;
|
||||
return c.json({
|
||||
event: {
|
||||
...normalized,
|
||||
bookedCount: ticketCount?.count || 0,
|
||||
availableSeats: normalized.capacity - (ticketCount?.count || 0),
|
||||
bookedCount,
|
||||
availableSeats: calculateAvailableSeats(normalized.capacity, bookedCount),
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -277,7 +279,7 @@ eventsRouter.get('/next/upcoming', async (c) => {
|
||||
event: {
|
||||
...normalized,
|
||||
bookedCount,
|
||||
availableSeats: normalized.capacity - bookedCount,
|
||||
availableSeats: calculateAvailableSeats(normalized.capacity, bookedCount),
|
||||
isFeatured: true,
|
||||
},
|
||||
});
|
||||
@@ -308,7 +310,7 @@ eventsRouter.get('/next/upcoming', async (c) => {
|
||||
event: {
|
||||
...normalized,
|
||||
bookedCount,
|
||||
availableSeats: normalized.capacity - bookedCount,
|
||||
availableSeats: calculateAvailableSeats(normalized.capacity, bookedCount),
|
||||
isFeatured: false,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user