refactor(stock): make expired reservations terminal
This commit is contained in:
@@ -86,4 +86,14 @@ class CartController extends Controller
|
||||
'message' => __('api.cart.item_removed'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function restart(Request $request, Tenant $tenant): CartResource
|
||||
{
|
||||
return CartResource::make(
|
||||
$this->cartService->restartExpired($tenant, $request),
|
||||
)->additional([
|
||||
'code' => 'cart.restarted',
|
||||
'message' => __('api.cart.restarted'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ class Cart extends Model
|
||||
|
||||
return DB::transaction(function () use ($catalogItemId, $variantId, $quantity): CartItem {
|
||||
$this->invalidateCurrentCheckout();
|
||||
app(StockReservationService::class)->assertCartReservationUsable($this);
|
||||
$selectedItem = $this->resolveScopedItem($catalogItemId, $variantId, true);
|
||||
$cartQuantity = (int) $this->items()
|
||||
->where('catalog_item_id', $catalogItemId)
|
||||
@@ -183,6 +184,7 @@ class Cart extends Model
|
||||
$excludedPurchaseId,
|
||||
): CartItem {
|
||||
$this->invalidateCurrentCheckout();
|
||||
app(StockReservationService::class)->assertCartReservationUsable($this);
|
||||
|
||||
/** @var CartItem $item */
|
||||
$item = $this->items()
|
||||
@@ -284,6 +286,7 @@ class Cart extends Model
|
||||
{
|
||||
DB::transaction(function () use ($cartItemId): void {
|
||||
$this->invalidateCurrentCheckout();
|
||||
app(StockReservationService::class)->assertCartReservationUsable($this);
|
||||
|
||||
/** @var CartItem $item */
|
||||
$item = $this->items()
|
||||
@@ -334,9 +337,14 @@ class Cart extends Model
|
||||
Purchase::STATUS_CREATED,
|
||||
Purchase::STATUS_PENDING_PAYMENT,
|
||||
], true)) {
|
||||
app(StockReservationService::class)->returnToCart($currentPurchase, $cart);
|
||||
$currentPurchase->update([
|
||||
'status' => Purchase::STATUS_SUPERSEDED,
|
||||
]);
|
||||
|
||||
$this->current_purchase_id = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
app(StockReservationService::class)->releaseForPurchase(
|
||||
|
||||
@@ -4,9 +4,12 @@ namespace App\Domains\Cart\Services;
|
||||
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Cart\Models\Cart;
|
||||
use App\Domains\Catalog\Models\StockReservation;
|
||||
use App\Domains\Catalog\Services\ExpireStockReservationsService;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
@@ -94,6 +97,45 @@ class CartService
|
||||
return $this->loadCart($cart, $tenant);
|
||||
}
|
||||
|
||||
public function restartExpired(Tenant $tenant, Request $request): Cart
|
||||
{
|
||||
$identity = $this->requireIdentity($request);
|
||||
$cart = $this->findCartOrFail($tenant, $identity);
|
||||
if ($cart->current_stock_reservation_id === null
|
||||
|| ! app(ExpireStockReservationsService::class)
|
||||
->expireIfOverdue($cart->current_stock_reservation_id)) {
|
||||
throw ValidationException::withMessages([
|
||||
'cart' => __('api.cart.reservation_not_expired'),
|
||||
]);
|
||||
}
|
||||
|
||||
$newCart = DB::transaction(function () use ($cart, $identity, $tenant): Cart {
|
||||
/** @var Cart $cart */
|
||||
$cart = Cart::query()->lockForUpdate()->findOrFail($cart->getKey());
|
||||
/** @var StockReservation|null $reservation */
|
||||
$reservation = $cart->current_stock_reservation_id === null
|
||||
? null
|
||||
: StockReservation::query()
|
||||
->lockForUpdate()
|
||||
->find($cart->current_stock_reservation_id);
|
||||
|
||||
if ($reservation?->status !== StockReservation::STATUS_EXPIRED) {
|
||||
throw ValidationException::withMessages([
|
||||
'cart' => __('api.cart.reservation_not_expired'),
|
||||
]);
|
||||
}
|
||||
|
||||
$cart->update([
|
||||
'status' => 'abandoned',
|
||||
'current_purchase_id' => null,
|
||||
]);
|
||||
|
||||
return $this->findOrCreateCart($tenant, $identity);
|
||||
});
|
||||
|
||||
return $this->loadCart($newCart, $tenant);
|
||||
}
|
||||
|
||||
public function makeGuestTokenCookie(string $guestToken): Cookie
|
||||
{
|
||||
$secure = (bool) config('session.secure');
|
||||
|
||||
@@ -6,6 +6,7 @@ use Illuminate\Support\Facades\Route;
|
||||
Route::prefix('tenants/{tenant:codigo}')
|
||||
->group(function (): void {
|
||||
Route::get('cart', [CartController::class, 'show']);
|
||||
Route::post('cart/restart', [CartController::class, 'restart']);
|
||||
Route::post('cart/items', [CartController::class, 'addItem']);
|
||||
Route::patch('cart/items/{cartItem}', [CartController::class, 'updateItemQuantity']);
|
||||
Route::delete('cart/items/{cartItem}', [CartController::class, 'removeItem']);
|
||||
|
||||
Reference in New Issue
Block a user