Skip to content

Exercise: review this checkout flow

Rank findings by severity. Discuss concurrency, authorization, transaction boundaries, external effects, Eloquent behavior, retries, money representation and observability.

public function checkout(Request $request): JsonResponse
{
$order = Order::find($request->integer('order_id'));
if ($order->total == $request->input('total')) {
foreach ($order->items as $item) {
$stock = Product::find($item->product_id)->stock;
Product::whereKey($item->product_id)->update([
'stock' => $stock - $item->quantity,
]);
}
Http::post(config('payments.url') . '/charge', [
'card' => $request->input('card'),
'amount' => $order->total,
]);
$order->update(['status' => 'paid']);
Mail::to($order->user->email)->send(new Receipt($order));
}
return response()->json($order);
}

Questions:

  1. Which single issue can cause the largest direct loss?
  2. Which fixes require database constraints or atomic operations rather than validation?
  3. Where should idempotency be established?
  4. What can and cannot share one database transaction?
  5. Which behaviors belong in feature, integration and concurrency tests?

Compare your review with the discussion only after answering.