Review
Capture berth deposit after transient-slip confirm
Berthline transient-slip checkout was blocking the HTTP response on Stripe capture (~400–900ms). Move capture off the request path with BackgroundTasks so guests get a confirmed berth immediately after we persist the booking and leave the PaymentIntent authorization in place for async capture.
FastAPITier 4fastapipaymentsbackground-tasksdurability
Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.
app/api/slips/bookings.py+22-4
| 48 | 48 | from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException | |
| 49 | 49 | from sqlalchemy.orm import Session | |
| 50 | 50 | ||
| 51 | 51 | from app.db import get_db | |
| 52 | 52 | from app.models import Booking | |
| 53 | - | from app.payments import capture_payment_intent | |
| 53 | + | from app.payments import capture_payment_intent, mark_capture_failed | |
| 54 | 54 | from app.schemas import BookingCreate, BookingOut | |
| 55 | 55 | ||
| 56 | 56 | router = APIRouter(prefix="/bookings", tags=["bookings"]) | |
| 57 | 57 | ||
| 58 | + | def _capture_after_confirm(payment_intent_id: str, booking_id: int) -> None: | |
| 59 | + | try: | |
| 60 | + | capture_payment_intent(payment_intent_id) | |
| 61 | + | except Exception: | |
| 62 | + | mark_capture_failed(booking_id, payment_intent_id) | |
| 63 | + | ||
| 58 | 64 | @router.post("", response_model=BookingOut) | |
| 59 | - | def create_booking(body: BookingCreate, db: Session = Depends(get_db)): | |
| 65 | + | def create_booking( | |
| 66 | + | body: BookingCreate, | |
| 67 | + | background_tasks: BackgroundTasks, | |
| 68 | + | db: Session = Depends(get_db), | |
| 69 | + | ): | |
| 60 | 70 | booking = Booking( | |
| 61 | 71 | slip_id=body.slip_id, | |
| 62 | 72 | guest_id=body.guest_id, | |
| 63 | 73 | payment_intent_id=body.payment_intent_id, | |
| 64 | 74 | status="confirmed", | |
| 65 | 75 | ) | |
| 66 | 76 | db.add(booking) | |
| 67 | 77 | db.commit() | |
| 68 | 78 | db.refresh(booking) | |
| 69 | - | capture_payment_intent(body.payment_intent_id) | |
| 79 | + | background_tasks.add_task( | |
| 80 | + | _capture_after_confirm, | |
| 81 | + | body.payment_intent_id, | |
| 82 | + | booking.id, | |
| 83 | + | ) | |
| 70 | - | return BookingOut.model_validate(booking) | |
| 84 | + | return BookingOut( | |
| 85 | + | id=booking.id, | |
| 86 | + | status=booking.status, | |
| 87 | + | payment_status="captured", | |
| 88 | + | ) |