From 82570fe94101e8547fad96e130222a03c60ce33f Mon Sep 17 00:00:00 2001 From: ncoronel Date: Tue, 25 Aug 2026 16:09:52 -0300 Subject: [PATCH] refactor(stock): propagate reservation expiration --- app/Domains/Cart/Services/CartService.php | 59 +------------------ .../ExpireStockReservationsService.php | 3 +- .../Checkout/ReleaseCheckoutService.php | 22 +++++-- 3 files changed, 22 insertions(+), 62 deletions(-) diff --git a/app/Domains/Cart/Services/CartService.php b/app/Domains/Cart/Services/CartService.php index fc0e573..f0226f0 100644 --- a/app/Domains/Cart/Services/CartService.php +++ b/app/Domains/Cart/Services/CartService.php @@ -4,6 +4,7 @@ namespace App\Domains\Cart\Services; use App\Domains\Auth\Models\User; use App\Domains\Cart\Models\Cart; +use App\Domains\Catalog\Exceptions\StockReservationExpiredException; use App\Domains\Catalog\Models\StockReservation; use App\Domains\Catalog\Services\ExpireStockReservationsService; use App\Domains\Tenant\Models\Tenant; @@ -126,7 +127,7 @@ class CartService } $cart->update([ - 'status' => 'abandoned', + 'status' => Cart::STATUS_ABANDONED, 'current_purchase_id' => null, ]); @@ -292,68 +293,14 @@ class CartService */ protected function findOrCreateCart(Tenant $tenant, array $identity): Cart { - return $this->resolveCart($tenant, $identity) - ?? $this->createCart($tenant, $identity); - } - - /** - * @param array{user_id: ?int, guest_token: ?string} $identity - */ - protected function resolveCart( - Tenant $tenant, - array $identity, - bool $replaceExpired = true, - ): ?Cart { $cart = $this->findCart($tenant, $identity); - - if ($cart?->status === Cart::STATUS_ACTIVE - && $cart->current_stock_reservation_id !== null - && app(ExpireStockReservationsService::class) - ->expireIfOverdue($cart->current_stock_reservation_id)) { - $cart = $this->findCart($tenant, $identity); - } - if ($cart?->status === Cart::STATUS_EXPIRED) { - if (! $replaceExpired) { - throw new StockReservationExpiredException; - } - - return $this->replaceExpiredCart($cart, $tenant, $identity); + throw new StockReservationExpiredException; } - if ($cart !== null) { return $cart; } - return null; - } - - /** - * @param array{user_id: ?int, guest_token: ?string} $identity - */ - protected function replaceExpiredCart(Cart $expiredCart, Tenant $tenant, array $identity): Cart - { - return DB::transaction(function () use ($expiredCart, $tenant, $identity): Cart { - /** @var Cart|null $lockedCart */ - $lockedCart = Cart::query()->lockForUpdate()->find($expiredCart->getKey()); - - if ($lockedCart?->status === Cart::STATUS_EXPIRED) { - $lockedCart->update([ - 'status' => Cart::STATUS_ABANDONED, - 'current_purchase_id' => null, - ]); - } - - return $this->findCart($tenant, $identity) - ?? $this->createCart($tenant, $identity); - }); - } - - /** - * @param array{user_id: ?int, guest_token: ?string} $identity - */ - protected function createCart(Tenant $tenant, array $identity): Cart - { $attributes = [ 'tenant_codigo' => $tenant->codigo, 'status' => Cart::STATUS_ACTIVE, diff --git a/app/Domains/Catalog/Services/ExpireStockReservationsService.php b/app/Domains/Catalog/Services/ExpireStockReservationsService.php index 33e87ff..58bf5a8 100644 --- a/app/Domains/Catalog/Services/ExpireStockReservationsService.php +++ b/app/Domains/Catalog/Services/ExpireStockReservationsService.php @@ -141,7 +141,7 @@ class ExpireStockReservationsService $cart = Cart::query() ->whereKey($cartId) ->where('current_stock_reservation_id', $reservationId) - ->where('status', 'active') + ->where('status', Cart::STATUS_ACTIVE) ->lockForUpdate() ->first(); if ($cart === null) { @@ -155,6 +155,7 @@ class ExpireStockReservationsService } $this->reservations->expire($reservation); + $cart->update(['status' => Cart::STATUS_EXPIRED]); return 'cart_reservations'; }); diff --git a/app/Domains/Purchase/Services/Checkout/ReleaseCheckoutService.php b/app/Domains/Purchase/Services/Checkout/ReleaseCheckoutService.php index 9879f91..a63ef14 100644 --- a/app/Domains/Purchase/Services/Checkout/ReleaseCheckoutService.php +++ b/app/Domains/Purchase/Services/Checkout/ReleaseCheckoutService.php @@ -129,13 +129,25 @@ class ReleaseCheckoutService return; } - if ($cart->status === 'active') { + if ($targetStatus === Purchase::STATUS_EXPIRED + && in_array($cart->status, [Cart::STATUS_ACTIVE, Cart::STATUS_CHECKOUT], true)) { + Cart::query() + ->whereKey($cart->getKey()) + ->where('current_purchase_id', $purchase->getKey()) + ->where('current_stock_reservation_id', $purchase->stock_reservation_id) + ->update([ + 'status' => Cart::STATUS_EXPIRED, + 'current_purchase_id' => null, + ]); + + return; + } + + if ($cart->status === Cart::STATUS_ACTIVE) { $cartUpdate = [ 'current_purchase_id' => null, + 'current_stock_reservation_id' => null, ]; - if ($targetStatus !== Purchase::STATUS_EXPIRED) { - $cartUpdate['current_stock_reservation_id'] = null; - } Cart::query() ->whereKey($cart->getKey()) @@ -145,7 +157,7 @@ class ReleaseCheckoutService return; } - if ($cart->status !== 'checkout') { + if ($cart->status !== Cart::STATUS_CHECKOUT) { return; }