feat(checkout): track current cart purchase

This commit is contained in:
2026-08-21 14:05:33 -03:00
parent a34d5cba1a
commit afd69b8393
17 changed files with 258 additions and 23 deletions

View File

@@ -193,6 +193,7 @@ class StartCheckoutService
),
$cart->getKey(),
);
$cart->update(['current_purchase_id' => $purchase->getKey()]);
$cartItems = $cart->items()->orderBy('id')->lockForUpdate()->get();
$this->loadCartItems($cartItems);
@@ -264,6 +265,7 @@ class StartCheckoutService
$cart->getTotalAmount(),
$cart->getKey(),
);
$cart->update(['current_purchase_id' => $purchase->getKey()]);
$purchase->items()->createMany($this->snapshots->fromCartItems($cartItems));
foreach ($cartItems as $cartItem) {
@@ -279,9 +281,52 @@ class StartCheckoutService
private function resolveCart(Tenant $tenant, int $userId, int $cartId): Cart
{
/** @var Cart|null $candidate */
$candidate = Cart::query()->find($cartId);
$this->assertCartCanCheckout($candidate, $tenant, $userId);
$candidatePurchaseId = $candidate->current_purchase_id;
$currentPurchase = $candidatePurchaseId === null
? null
: Purchase::query()->lockForUpdate()->find($candidatePurchaseId);
/** @var Cart|null $cart */
$cart = Cart::query()->lockForUpdate()->find($cartId);
$this->assertCartCanCheckout($cart, $tenant, $userId);
if ($cart->current_purchase_id !== $candidatePurchaseId) {
if ($cart->current_purchase_id !== null) {
throw ValidationException::withMessages([
'cart_id' => __('api.purchase.checkout_in_progress'),
]);
}
$currentPurchase = null;
}
if ($currentPurchase?->status === Purchase::STATUS_PAID) {
throw ValidationException::withMessages([
'cart_id' => __('api.purchase.checkout_in_progress'),
]);
}
if ($currentPurchase !== null && in_array($currentPurchase->status, [
Purchase::STATUS_CREATED,
Purchase::STATUS_PENDING_PAYMENT,
], true)) {
$currentPurchase->update([
'status' => Purchase::STATUS_SUPERSEDED,
'expires_at' => null,
]);
}
return $cart;
}
private function assertCartCanCheckout(?Cart $cart, Tenant $tenant, int $userId): void
{
if ($cart === null || $cart->tenant_codigo !== $tenant->codigo || $cart->user_id !== $userId) {
throw new NotFoundHttpException('Cart not found for tenant.');
}
@@ -291,16 +336,6 @@ class StartCheckoutService
'cart_id' => __('api.purchase.inactive_cart'),
]);
}
if ($cart->purchases()
->whereIn('status', [Purchase::STATUS_CREATED, Purchase::STATUS_PENDING_PAYMENT])
->exists()) {
throw ValidationException::withMessages([
'cart_id' => __('api.purchase.checkout_in_progress'),
]);
}
return $cart;
}
/** @param Collection<int, CartItem> $cartItems */