feat(cart): enhance item update functionality to support variant changes and stock management; update related request validation and resource formatting; add tests for variant handling in cart
This commit is contained in:
@@ -124,27 +124,85 @@ class Cart extends Model
|
||||
});
|
||||
}
|
||||
|
||||
public function updateItem(int $cartItemId, int $quantity): CartItem
|
||||
{
|
||||
public function updateItem(
|
||||
int $cartItemId,
|
||||
int $quantity,
|
||||
?int $variantId = null,
|
||||
bool $updateVariant = false,
|
||||
): CartItem {
|
||||
if ($quantity <= 0) {
|
||||
throw ValidationException::withMessages([
|
||||
'cantidad' => __('api.cart.positive_quantity'),
|
||||
]);
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($cartItemId, $quantity): CartItem {
|
||||
return DB::transaction(function () use (
|
||||
$cartItemId,
|
||||
$quantity,
|
||||
$variantId,
|
||||
$updateVariant,
|
||||
): CartItem {
|
||||
/** @var CartItem $item */
|
||||
$item = $this->items()
|
||||
->where('id', $cartItemId)
|
||||
->lockForUpdate()
|
||||
->firstOrFail();
|
||||
|
||||
$selectedItem = $this->resolveScopedItem(
|
||||
$currentSelection = $this->resolveScopedItem(
|
||||
$item->catalog_item_id,
|
||||
$item->variant_id,
|
||||
true,
|
||||
);
|
||||
$inventoryService = app(CatalogInventoryService::class);
|
||||
|
||||
if ($updateVariant && $variantId !== $item->variant_id) {
|
||||
$nextSelection = $this->resolveScopedItem(
|
||||
$item->catalog_item_id,
|
||||
$variantId,
|
||||
true,
|
||||
);
|
||||
$otherVariantsQuantity = (int) $this->items()
|
||||
->where('catalog_item_id', $item->catalog_item_id)
|
||||
->whereKeyNot($item->getKey())
|
||||
->sum('cantidad');
|
||||
$this->assertUserPurchaseLimit(
|
||||
$nextSelection,
|
||||
$otherVariantsQuantity + $quantity,
|
||||
);
|
||||
|
||||
$inventoryService->release($currentSelection, $item->cantidad);
|
||||
$availableQuantity = $inventoryService->availableQuantity($nextSelection);
|
||||
|
||||
if ($availableQuantity !== null && $availableQuantity < $quantity) {
|
||||
throw ValidationException::withMessages([
|
||||
'variant_id' => __('api.cart.insufficient_stock', ['max' => $availableQuantity]),
|
||||
]);
|
||||
}
|
||||
|
||||
$targetItem = $this->items()
|
||||
->where('catalog_item_id', $item->catalog_item_id)
|
||||
->where('variant_id', $variantId)
|
||||
->whereKeyNot($item->getKey())
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
$inventoryService->reserve($nextSelection, $quantity);
|
||||
|
||||
if ($targetItem !== null) {
|
||||
$targetItem->cantidad += $quantity;
|
||||
$targetItem->save();
|
||||
$item->delete();
|
||||
|
||||
return $targetItem->fresh();
|
||||
}
|
||||
|
||||
$item->variant_id = $variantId;
|
||||
$item->cantidad = $quantity;
|
||||
$item->save();
|
||||
|
||||
return $item->fresh();
|
||||
}
|
||||
|
||||
$delta = $quantity - $item->cantidad;
|
||||
|
||||
if ($delta > 0) {
|
||||
@@ -153,12 +211,12 @@ class Cart extends Model
|
||||
->whereKeyNot($item->getKey())
|
||||
->sum('cantidad');
|
||||
$this->assertUserPurchaseLimit(
|
||||
$selectedItem,
|
||||
$currentSelection,
|
||||
$otherVariantsQuantity + $quantity,
|
||||
);
|
||||
}
|
||||
|
||||
$availableQuantity = $inventoryService->availableQuantity($selectedItem);
|
||||
$availableQuantity = $inventoryService->availableQuantity($currentSelection);
|
||||
|
||||
if ($delta > 0 && $availableQuantity !== null && $availableQuantity < $delta) {
|
||||
$maxAvailable = $availableQuantity + $item->cantidad;
|
||||
@@ -171,11 +229,11 @@ class Cart extends Model
|
||||
$item->save();
|
||||
|
||||
if ($delta > 0) {
|
||||
$inventoryService->reserve($selectedItem, $delta);
|
||||
$inventoryService->reserve($currentSelection, $delta);
|
||||
}
|
||||
|
||||
if ($delta < 0) {
|
||||
$inventoryService->release($selectedItem, abs($delta));
|
||||
$inventoryService->release($currentSelection, abs($delta));
|
||||
}
|
||||
|
||||
return $item->fresh();
|
||||
|
||||
Reference in New Issue
Block a user