Backend and frontend updates: auth, email, payments, events, tickets; carrousel images; mobile event detail layout; i18n
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Hono } from 'hono';
|
||||
import { streamSSE } from 'hono/streaming';
|
||||
import { db, dbGet, tickets, payments } from '../db/index.js';
|
||||
import { db, dbGet, dbAll, tickets, payments } from '../db/index.js';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { getNow } from '../lib/utils.js';
|
||||
import { verifyWebhookPayment, getPaymentStatus } from '../lib/lnbits.js';
|
||||
@@ -152,40 +152,63 @@ lnbitsRouter.post('/webhook', async (c) => {
|
||||
|
||||
/**
|
||||
* Handle successful payment
|
||||
* Supports multi-ticket bookings - confirms all tickets in the booking
|
||||
*/
|
||||
async function handlePaymentComplete(ticketId: string, paymentHash: string) {
|
||||
const now = getNow();
|
||||
|
||||
// Check if already confirmed to avoid duplicate updates
|
||||
// Get the ticket to check for booking ID
|
||||
const existingTicket = await dbGet<any>(
|
||||
(db as any).select().from(tickets).where(eq((tickets as any).id, ticketId))
|
||||
);
|
||||
|
||||
if (existingTicket?.status === 'confirmed') {
|
||||
if (!existingTicket) {
|
||||
console.error(`Ticket ${ticketId} not found for payment confirmation`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingTicket.status === 'confirmed') {
|
||||
console.log(`Ticket ${ticketId} already confirmed, skipping update`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update ticket status to confirmed
|
||||
await (db as any)
|
||||
.update(tickets)
|
||||
.set({ status: 'confirmed' })
|
||||
.where(eq((tickets as any).id, ticketId));
|
||||
// Get all tickets in this booking (if multi-ticket)
|
||||
let ticketsToConfirm: any[] = [existingTicket];
|
||||
|
||||
// Update payment status to paid
|
||||
await (db as any)
|
||||
.update(payments)
|
||||
.set({
|
||||
status: 'paid',
|
||||
reference: paymentHash,
|
||||
paidAt: now,
|
||||
updatedAt: now,
|
||||
})
|
||||
.where(eq((payments as any).ticketId, ticketId));
|
||||
if (existingTicket.bookingId) {
|
||||
// This is a multi-ticket booking - get all tickets with same bookingId
|
||||
ticketsToConfirm = await dbAll(
|
||||
(db as any)
|
||||
.select()
|
||||
.from(tickets)
|
||||
.where(eq((tickets as any).bookingId, existingTicket.bookingId))
|
||||
);
|
||||
console.log(`Multi-ticket booking detected: ${ticketsToConfirm.length} tickets to confirm`);
|
||||
}
|
||||
|
||||
console.log(`Ticket ${ticketId} confirmed via Lightning payment (hash: ${paymentHash})`);
|
||||
// Confirm all tickets in the booking
|
||||
for (const ticket of ticketsToConfirm) {
|
||||
// Update ticket status to confirmed
|
||||
await (db as any)
|
||||
.update(tickets)
|
||||
.set({ status: 'confirmed' })
|
||||
.where(eq((tickets as any).id, ticket.id));
|
||||
|
||||
// Update payment status to paid
|
||||
await (db as any)
|
||||
.update(payments)
|
||||
.set({
|
||||
status: 'paid',
|
||||
reference: paymentHash,
|
||||
paidAt: now,
|
||||
updatedAt: now,
|
||||
})
|
||||
.where(eq((payments as any).ticketId, ticket.id));
|
||||
|
||||
console.log(`Ticket ${ticket.id} confirmed via Lightning payment (hash: ${paymentHash})`);
|
||||
}
|
||||
|
||||
// Get payment for sending receipt
|
||||
// Get primary payment for sending receipt
|
||||
const payment = await dbGet<any>(
|
||||
(db as any)
|
||||
.select()
|
||||
@@ -194,6 +217,7 @@ async function handlePaymentComplete(ticketId: string, paymentHash: string) {
|
||||
);
|
||||
|
||||
// Send confirmation emails asynchronously
|
||||
// For multi-ticket bookings, send email with all ticket info
|
||||
Promise.all([
|
||||
emailService.sendBookingConfirmation(ticketId),
|
||||
payment ? emailService.sendPaymentReceipt(payment.id) : Promise.resolve(),
|
||||
|
||||
Reference in New Issue
Block a user