feat(inventory): add traceable cart stock reservations

This commit is contained in:
2026-08-19 12:06:19 -03:00
parent 15878cd9ba
commit e6c4b40a37
11 changed files with 417 additions and 11 deletions

View File

@@ -7,6 +7,8 @@ use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Inventory;
use App\Domains\Catalog\Models\Variant;
use App\Domains\Catalog\Services\CatalogInventoryService;
use App\Domains\Catalog\Services\StockReservationService;
use App\Domains\Purchase\Models\Purchase;
use App\Domains\Purchase\Services\UserPurchaseLimitService;
use App\Domains\Tenant\Models\Tenant;
use Illuminate\Database\Eloquent\Attributes\Fillable;
@@ -24,6 +26,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
'user_id',
'guest_token',
'status',
'origin',
])]
class Cart extends Model
{
@@ -32,6 +35,10 @@ class Cart extends Model
protected $table = 'carritos';
public const ORIGIN_USER = 'user';
public const ORIGIN_DIRECT_CHECKOUT = 'direct_checkout';
protected function casts(): array
{
return [
@@ -63,6 +70,12 @@ class Cart extends Model
return $this->hasMany(CartItem::class, 'cart_id');
}
/** @return HasMany<Purchase, $this> */
public function purchases(): HasMany
{
return $this->hasMany(Purchase::class, 'cart_id');
}
public function getTotalAmount(): float
{
$items = $this->relationLoaded('items')
@@ -114,11 +127,12 @@ class Cart extends Model
'cantidad' => $quantity,
]);
} else {
app(StockReservationService::class)->ensure($item, $selectedItem);
$item->cantidad += $quantity;
$item->save();
}
$inventoryService->reserve($selectedItem, $quantity);
app(StockReservationService::class)->reserve($item, $selectedItem, $quantity);
return $item->fresh();
});
@@ -170,7 +184,7 @@ class Cart extends Model
$otherVariantsQuantity + $quantity,
);
$inventoryService->release($currentSelection, $item->cantidad);
app(StockReservationService::class)->release($item, $currentSelection, $item->cantidad);
$availableQuantity = $inventoryService->availableQuantity($nextSelection);
if ($availableQuantity !== null && $availableQuantity < $quantity) {
@@ -186,11 +200,11 @@ class Cart extends Model
->lockForUpdate()
->first();
$inventoryService->reserve($nextSelection, $quantity);
if ($targetItem !== null) {
app(StockReservationService::class)->ensure($targetItem, $nextSelection);
$targetItem->cantidad += $quantity;
$targetItem->save();
app(StockReservationService::class)->reserve($targetItem, $nextSelection, $quantity);
$item->delete();
return $targetItem->fresh();
@@ -199,6 +213,7 @@ class Cart extends Model
$item->variant_id = $variantId;
$item->cantidad = $quantity;
$item->save();
app(StockReservationService::class)->reserve($item, $nextSelection, $quantity);
return $item->fresh();
}
@@ -225,17 +240,17 @@ class Cart extends Model
]);
}
$item->cantidad = $quantity;
$item->save();
if ($delta > 0) {
$inventoryService->reserve($currentSelection, $delta);
app(StockReservationService::class)->reserve($item, $currentSelection, $delta);
}
if ($delta < 0) {
$inventoryService->release($currentSelection, abs($delta));
app(StockReservationService::class)->release($item, $currentSelection, abs($delta));
}
$item->cantidad = $quantity;
$item->save();
return $item->fresh();
});
}
@@ -254,7 +269,8 @@ class Cart extends Model
$item->variant_id,
true,
);
app(CatalogInventoryService::class)->release(
app(StockReservationService::class)->release(
$item,
$selectedItem,
$item->cantidad,
);