refactor(stock): propagate reservation expiration

This commit is contained in:
2026-08-25 16:09:52 -03:00
parent d2a2b323e0
commit 82570fe941
3 changed files with 22 additions and 62 deletions

View File

@@ -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,

View File

@@ -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';
});

View File

@@ -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;
}