diff --git a/prisma/migrations/20260530173000_add_last_booked_at/migration.sql b/prisma/migrations/20260530173000_add_last_booked_at/migration.sql new file mode 100644 index 0000000..8df5aef --- /dev/null +++ b/prisma/migrations/20260530173000_add_last_booked_at/migration.sql @@ -0,0 +1,2 @@ +ALTER TABLE "Carbet" +ADD COLUMN "lastBookedAt" TIMESTAMP(3); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index abe74c4..ee7a327 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -109,6 +109,7 @@ model Carbet { pirogueDurationMin Int capacity Int status CarbetStatus @default(DRAFT) + lastBookedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/src/app/api/carbets/[carbetId]/last-booked/route.ts b/src/app/api/carbets/[carbetId]/last-booked/route.ts new file mode 100644 index 0000000..db20bf8 --- /dev/null +++ b/src/app/api/carbets/[carbetId]/last-booked/route.ts @@ -0,0 +1,25 @@ +import { NextResponse } from "next/server"; + +import { prisma } from "@/lib/prisma"; + +export const runtime = "nodejs"; + +export async function GET( + _request: Request, + { params }: { params: Promise<{ carbetId: string }> }, +) { + const { carbetId } = await params; + + const carbet = await prisma.carbet.findUnique({ + where: { id: carbetId }, + select: { lastBookedAt: true }, + }); + + if (!carbet) { + return NextResponse.json({ error: "Carbet introuvable." }, { status: 404 }); + } + + return NextResponse.json({ + lastBookedAt: carbet.lastBookedAt?.toISOString() ?? null, + }); +} diff --git a/src/app/api/stripe/webhook/route.ts b/src/app/api/stripe/webhook/route.ts index d3bc17a..519e180 100644 --- a/src/app/api/stripe/webhook/route.ts +++ b/src/app/api/stripe/webhook/route.ts @@ -6,6 +6,7 @@ import { PaymentStatus, SubscriptionStatus, } from "@/generated/prisma/enums"; +import { refreshCarbetLastBookedAt } from "@/lib/carbet-last-booked"; import { prisma } from "@/lib/prisma"; import { fromStripeTimestamp, getStripeClient } from "@/lib/stripe"; @@ -36,13 +37,17 @@ async function handleCheckoutCompleted(session: Stripe.Checkout.Session) { const type = session.metadata?.type; if (type === "booking" && bookingId) { - await prisma.booking.update({ + const booking = await prisma.booking.update({ where: { id: bookingId }, data: { paymentStatus: PaymentStatus.SUCCEEDED, status: BookingStatus.CONFIRMED, }, + select: { + carbetId: true, + }, }); + await refreshCarbetLastBookedAt(booking.carbetId); return; } @@ -78,13 +83,17 @@ async function handlePaymentIntentFailed(paymentIntent: Stripe.PaymentIntent) { return; } - await prisma.booking.update({ + const booking = await prisma.booking.update({ where: { id: bookingId }, data: { paymentStatus: PaymentStatus.FAILED, status: BookingStatus.CANCELLED, }, + select: { + carbetId: true, + }, }); + await refreshCarbetLastBookedAt(booking.carbetId); } async function handleSubscriptionUpdated(subscription: Stripe.Subscription) { diff --git a/src/lib/carbet-last-booked.ts b/src/lib/carbet-last-booked.ts new file mode 100644 index 0000000..30d9ce5 --- /dev/null +++ b/src/lib/carbet-last-booked.ts @@ -0,0 +1,24 @@ +import { BookingStatus } from "@/generated/prisma/enums"; +import { prisma } from "@/lib/prisma"; + +export async function refreshCarbetLastBookedAt(carbetId: string): Promise { + const latestConfirmedBooking = await prisma.booking.findFirst({ + where: { + carbetId, + status: BookingStatus.CONFIRMED, + }, + orderBy: { + updatedAt: "desc", + }, + select: { + updatedAt: true, + }, + }); + + await prisma.carbet.update({ + where: { id: carbetId }, + data: { + lastBookedAt: latestConfirmedBooking?.updatedAt ?? null, + }, + }); +}