output:
Chunk ID: a22f2f
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1339
Output:

**File:** `tests/Browser/Storefront/InventoryTest.php`

**Purpose:** Verify that inventory policies are correctly enforced on the storefront - deny-policy blocks purchasing when out of stock, continue-policy allows backorders.

### Inventory Policy Decision Matrix

| Stock Level | Policy | Storefront Display | Add-to-Cart |
|-------------|--------|--------------------|-------------|
| > 0 | `deny` | "Add to cart" button enabled | Allowed |
| > 0 | `continue` | "Add to cart" button enabled | Allowed |
| 0 | `deny` | "Sold out" text, button disabled | Blocked |
| 0 | `continue` | "Available on backorder" text, button enabled | Allowed |

---

### Test 11.1: Blocks add-to-cart for out-of-stock deny-policy product

**Preconditions:** Product #17 (0 stock, inventory policy = deny)

**Steps:**
1. Navigate to the product page for Product #17 (use actual handle from seeder)

**Expected Results:**
- Page displays "Sold out"
- "Add to cart" button is disabled or hidden (not clickable)
- No JavaScript errors

---

### Test 11.2: Allows add-to-cart for out-of-stock continue-policy product

**Preconditions:** Product #18 (0 stock, inventory policy = continue)

**Steps:**
1. Navigate to the product page for Product #18 (use actual handle from seeder)
2. Verify "Available on backorder" is displayed
3. Click "Add to cart"
4. Navigate to `/cart`

**Expected Results:**
- "Available on backorder" is visible on the product page
- Add to cart succeeds
- Cart page shows the product
- No JavaScript errors

---

### Test 11.3: Shows correct stock status for in-stock product

**Preconditions:** Product #1 (in stock)

**Steps:**
1. Navigate to `/products/classic-cotton-t-shirt`

**Expected Results:**
- Page displays "Add to cart" button (enabled)
- "Sold out" is NOT displayed
- "Available on backorder" is NOT displayed
- No JavaScript errors

---

### Test 11.4: Prevents adding more than available stock for deny-policy product

**Preconditions:** A product with limited stock (deny policy)

**Steps:**
1. Navigate to `/products/classic-cotton-t-shirt`
2. Click "M" to select size M
3. Click "Black" to select color Black
4. Click "Add to cart"
5. Navigate to `/cart`
6. Attempt to increase quantity beyond the available stock level

**Expected Results:**
- System prevents exceeding available inventory (either caps quantity or shows error)
- No JavaScript errors

**Total: 4 tests**

---

## Suite 12: Tenant Isolation

**File:** `tests/Browser/Storefront/TenantIsolationTest.php`

**Purpose:** Verify that multi-store tenant isolation is enforced - data from one store never leaks into another store's storefront or admin panel.

### Isolation Requirements

```mermaid
flowchart LR
    subgraph Store1[Store 1 - Acme Fashion]
        S1Products[Fashion Products]
        S1Orders[Fashion Orders]
        S1Customers[Fashion Customers]
    end
    subgraph Store2[Store 2 - Different Store]
        S2Products[Other Products]
        S2Orders[Other Orders]
        S2Customers[Other Customers]
    end
    S1Products -.-x S2Products
    S1Orders -.-x S2Orders
    S1Customers -.-x S2Customers
```

Dashed X lines indicate these must NEVER cross. No data from Store 2 should ever appear when browsing Store 1, and vice versa.

---

### Test 12.1: Store 1 only shows Store 1 products

**Preconditions:** Seeded Store 1 products

**Steps:**
1. Navigate to `/` (resolved to Store 1 via acme-fashion.test domain)

**Expected Results:**
- Page displays "Acme Fashion"
- Page displays "Classic Cotton T-Shirt"
- Products from other stores (e.g., electronics from Store 2) are absent
- No JavaScript errors

---

### Test 12.2: Store 1 collections only contain Store 1 products

**Preconditions:** Seeded collections

**Steps:**
1. Navigate to `/collections/t-shirts`

**Expected Results:**
- Page displays "T-Shirts"
- Only Store 1 products appear in the collection grid
- No JavaScript errors

---

### Test 12.3: Admin cannot access other store data

**Preconditions:** Logged in as admin@acme.test (Store 1 owner)

**Steps:**
1. Navigate to `/admin/login`
2. Log in as admin (email: `admin@acme.test`, password: `password`)
3. Click "Products" in the sidebar
4. Review the product list
5. Click "Orders" in the sidebar
6. Review the order list

**Expected Results:**
- All products listed belong to Store 1 only
- All orders listed belong to Store 1 only
- No cross-store data is visible
- No JavaScript errors

---

### Test 12.4: Search only returns current store products

**Preconditions:** Seeded Store 1 products

**Steps:**
1. Navigate to `/search?q=product`

**Expected Results:**
- Only Store 1 products appear in search results
- No cross-store data leakage
- No JavaScript errors

---

### Test 12.5: Customer accounts are scoped to their store

**Preconditions:** customer@acme.test seeded for Store 1

**Steps:**
1. Navigate to `/account/login`
2. Enter email: `customer@acme.test`
3. Enter password: `password`
4. Click "Log in"
5. Click "Orders"

**Expected Results:**
- Customer only sees Store 1 orders (#1001, #1002, #1004)
- No JavaScript errors

**Total: 5 tests**

---

## Suite 13: Responsive / Mobile

**File:** `tests/Browser/Storefront/ResponsiveTest.php`

**Purpose:** Verify that the storefront and admin panel render and function correctly on mobile (375x812) and tablet (768x1024) viewports.

### Viewport Definitions


command: rg "inventory|stock|quantity_available|Out of stock|Available on backorder|addLine|add to cart" -n app resources tests/Feature tests/Browser specs/05-BUSINESS-LOGIC.md | sed -n '1,260p'

type: search

cmd: rg 'inventory|stock|quantity_available|Out of stock|Available on backorder|addLine|add to cart' -n app resources tests/Feature tests/Browser specs/05-BUSINESS-LOGIC.md

query: inventory|stock|quantity_available|Out of stock|Available on backorder|addLine|add to cart

path: app

aggregated_output:
tests/Browser/Storefront/BrowsingTest.php:104:test('shows out of stock messaging for deny policy product', function (): void {
tests/Browser/Storefront/BrowsingTest.php:107:        ->assertSee('Out of stock')
tests/Browser/Storefront/BrowsingTest.php:117:        ->assertSee('Available on backorder')
specs/05-BUSINESS-LOGIC.md:80:products, collections, customers, orders, carts, checkouts, discounts, shipping_zones, themes, pages, navigation_menus, analytics_events, analytics_daily, webhook_subscriptions, inventory_items, search_queries.
specs/05-BUSINESS-LOGIC.md:167:            SKIP (preserve existing variant - prices, SKUs, inventory intact)
specs/05-BUSINESS-LOGIC.md:203:Each `product_variant` has exactly one `inventory_item` record (created automatically when the variant is created).
specs/05-BUSINESS-LOGIC.md:207:| `quantity_on_hand` | Total physical stock count |
specs/05-BUSINESS-LOGIC.md:213:Per-variant policy stored in `inventory_items.policy`:
specs/05-BUSINESS-LOGIC.md:217:| `deny` | Block add-to-cart when available <= 0. Storefront displays "Out of stock". |
specs/05-BUSINESS-LOGIC.md:218:| `continue` | Allow add-to-cart regardless of stock level. When available <= 0, storefront displays "Available on backorder". |
specs/05-BUSINESS-LOGIC.md:232:        C -->|Restock on refund| A
specs/05-BUSINESS-LOGIC.md:243:| **Restock** | Refund processed with restock flag | +quantity | No change | None |
specs/05-BUSINESS-LOGIC.md:306:- Re-check inventory policy for the new quantity.
specs/05-BUSINESS-LOGIC.md:343:- Releases any reserved inventory associated with active checkouts for these carts.
specs/05-BUSINESS-LOGIC.md:433:    note right of completed : Order created, inventory committed
specs/05-BUSINESS-LOGIC.md:434:    note right of expired : Reserved inventory released
specs/05-BUSINESS-LOGIC.md:498:2. Reserve inventory for all cart lines (call InventoryService.reserve for each line).
specs/05-BUSINESS-LOGIC.md:521:           Release reserved inventory
specs/05-BUSINESS-LOGIC.md:531:           inventoryAction = 'commit'
specs/05-BUSINESS-LOGIC.md:536:           inventoryAction = 'keep_reserved'
specs/05-BUSINESS-LOGIC.md:557:    8. IF inventoryAction = 'commit':
specs/05-BUSINESS-LOGIC.md:560:       // Note: for bank_transfer, inventory stays reserved until admin confirms payment
specs/05-BUSINESS-LOGIC.md:569:    12. IF inventoryAction = 'commit' AND all order lines are digital:
specs/05-BUSINESS-LOGIC.md:585:1. If inventory was reserved (status was `payment_selected`): release all reserved inventory via InventoryService.release.
specs/05-BUSINESS-LOGIC.md:979:    Backend->>Backend: Reserve inventory (if not already reserved)
specs/05-BUSINESS-LOGIC.md:986:            Backend->>Backend: Commit inventory, mark cart converted
specs/05-BUSINESS-LOGIC.md:989:            Backend->>Backend: Release reserved inventory
specs/05-BUSINESS-LOGIC.md:1037:5. Backend calls `InventoryService.commit()` for each order line (converts reserved stock to committed).
specs/05-BUSINESS-LOGIC.md:1050:1. Release reserved inventory via `InventoryService.release()`.
specs/05-BUSINESS-LOGIC.md:1130:| `restock` | boolean | No | Whether to restock inventory for refunded items. |
specs/05-BUSINESS-LOGIC.md:1160:    7. IF request.restock = true:
specs/05-BUSINESS-LOGIC.md:1162:           CALL InventoryService.restock(variant, quantity)
specs/05-BUSINESS-LOGIC.md:1255:The fulfillment guard interacts with inventory differently depending on the payment method:
specs/05-BUSINESS-LOGIC.md:1259:| `credit_card` / `paypal` | Inventory committed (on_hand decremented, reserved decremented) | N/A (already committed) | No inventory change |
specs/05-BUSINESS-LOGIC.md:1260:| `bank_transfer` | Inventory reserved only (reserved incremented) | Inventory committed (on_hand decremented, reserved decremented) | No inventory change |
specs/05-BUSINESS-LOGIC.md:1262:For bank transfer orders, inventory is held in a reserved state until the admin confirms payment. If the order is auto-cancelled (see Section 10.8), the reserved inventory is released back.
specs/05-BUSINESS-LOGIC.md:1595:| `OrderRefunded` | Send refund notification email, dispatch webhooks (`order.refunded`), optionally restock |
specs/05-BUSINESS-LOGIC.md:1599:| `CheckoutExpired` | Release reserved inventory |
specs/05-BUSINESS-LOGIC.md:1604:| `OrderPaid` | Update order status, commit inventory (bank transfer confirmation), auto-fulfill digital products |
specs/05-BUSINESS-LOGIC.md:1608:| `OrderCancelled` | Release reserved inventory, send cancellation email |
specs/05-BUSINESS-LOGIC.md:1619:| `App\Jobs\ExpireAbandonedCheckouts` | Every 15 minutes | Expire checkouts idle for 24+ hours, release reserved inventory |
specs/05-BUSINESS-LOGIC.md:1640:| InventoryService | `App\Services` | Reserve, release, commit, restock operations |
specs/05-BUSINESS-LOGIC.md:1651:| RefundService | `App\Services` | Refund processing and inventory restock |
tests/Browser/SmokeTest.php:79:        '/admin/invent…21464 chars truncated…  $inventory = $variant->inventoryItem;
app/Http/Resources/Storefront/V1/SearchProductResource.php:42:        if ($inventory === null) {
app/Http/Resources/Storefront/V1/SearchProductResource.php:46:        return $inventory->availableQuantity() > 0
app/Http/Resources/Storefront/V1/SearchProductResource.php:47:            || $inventory->policy === InventoryPolicy::Continue;
app/Livewire/Admin/Inventory/Index.php:17:    public string $stockFilter = 'all';
app/Livewire/Admin/Inventory/Index.php:42:            ->when($this->stockFilter === 'low', fn (Builder $query) => $query->whereRaw('(quantity_on_hand - quantity_reserved) BETWEEN 1 AND 10'))
app/Livewire/Admin/Inventory/Index.php:43:            ->when($this->stockFilter === 'out', fn (Builder $query) => $query->whereRaw('(quantity_on_hand - quantity_reserved) <= 0'))
app/Livewire/Admin/Inventory/Index.php:50:        return view('livewire.admin.inventory.index', [
app/Livewire/Admin/Settings/Notifications.php:75:                    'low_stock_alerts_enabled' => $validated['lowStockAlertsEnabled'],
app/Livewire/Admin/Settings/Notifications.php:76:                    'low_stock_threshold' => $validated['lowStockThreshold'],
app/Livewire/Admin/Settings/Notifications.php:106:        $this->lowStockAlertsEnabled = (bool) data_get($settings, 'notifications.low_stock_alerts_enabled', true);
app/Livewire/Admin/Settings/Notifications.php:107:        $this->lowStockThreshold = (int) data_get($settings, 'notifications.low_stock_threshold', 5);
app/Livewire/Storefront/Collections/Show.php:70:            ->with(['variants.inventoryItem'])
app/Livewire/Storefront/Collections/Show.php:75:                $query->whereHas('variants.inventoryItem', function (Builder $query): void {
app/Livewire/Admin/Products/Form.php:82:            $this->product = $product->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Admin/Products/Form.php:232:        $this->product = $product->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Admin/Products/Form.php:250:        $this->product = $product->refresh()->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Admin/Products/Form.php:403:                'quantity' => $variant->inventoryItem?->quantity_on_hand ?? 0,
app/Livewire/Admin/Products/Form.php:800:        $this->product = $this->productForAction()->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Storefront/Search/Index.php:110:            'in_stock' => $this->inStock,
app/Livewire/Storefront/Home.php:26:            ->with(['variants.inventoryItem'])
app/Livewire/Storefront/Products/Show.php:52:        $max = $variant?->inventoryItem?->policy === InventoryPolicy::Deny
app/Livewire/Storefront/Products/Show.php:53:            ? max(1, $variant->inventoryItem->availableQuantity())
app/Livewire/Storefront/Products/Show.php:78:        app(CartService::class)->addLine(
app/Livewire/Storefront/Products/Show.php:109:            ->with(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections'])
app/Livewire/Storefront/Products/Show.php:141:        $inventory = $variant->inventoryItem;
app/Livewire/Storefront/Products/Show.php:143:        return $inventory?->policy === InventoryPolicy::Continue
app/Livewire/Storefront/Products/Show.php:144:            || ($inventory?->availableQuantity() ?? 0) >= $this->quantity;
app/Livewire/Storefront/Products/Show.php:150:    public function stockState(): array
app/Livewire/Storefront/Products/Show.php:153:        $inventory = $variant?->inventoryItem;
app/Livewire/Storefront/Products/Show.php:155:        if (! $inventory) {
app/Livewire/Storefront/Products/Show.php:159:        if ($inventory->policy === InventoryPolicy::Continue && $inventory->availableQuantity() <= 0) {
app/Livewire/Storefront/Products/Show.php:160:            return ['message' => 'Available on backorder', 'class' => 'text-blue-700 dark:text-blue-300'];
app/Livewire/Storefront/Products/Show.php:163:        if ($inventory->availableQuantity() <= 0) {
app/Livewire/Storefront/Products/Show.php:164:            return ['message' => 'Out of stock', 'class' => 'text-red-700 dark:text-red-300'];
app/Livewire/Storefront/Products/Show.php:167:        if ($inventory->availableQuantity() <= 10) {
app/Livewire/Storefront/Products/Show.php:168:            return ['message' => "Only {$inventory->availableQuantity()} left in stock", 'class' => 'text-amber-700 dark:text-amber-300'];
app/Livewire/Storefront/Products/Show.php:171:        return ['message' => 'In stock', 'class' => 'text-green-700 dark:text-green-300'];
app/Livewire/Storefront/Products/Show.php:181:            'stockState' => $this->stockState(),
app/Livewire/Admin/Products/Index.php:93:            ->with(['variants.inventoryItem'])

status: completed


output:
Chunk ID: 009dcb
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 7866
Output:
tests/Browser/Storefront/BrowsingTest.php:104:test('shows out of stock messaging for deny policy product', function (): void {
tests/Browser/Storefront/BrowsingTest.php:107:        ->assertSee('Out of stock')
tests/Browser/Storefront/BrowsingTest.php:117:        ->assertSee('Available on backorder')
specs/05-BUSINESS-LOGIC.md:80:products, collections, customers, orders, carts, checkouts, discounts, shipping_zones, themes, pages, navigation_menus, analytics_events, analytics_daily, webhook_subscriptions, inventory_items, search_queries.
specs/05-BUSINESS-LOGIC.md:167:            SKIP (preserve existing variant - prices, SKUs, inventory intact)
specs/05-BUSINESS-LOGIC.md:203:Each `product_variant` has exactly one `inventory_item` record (created automatically when the variant is created).
specs/05-BUSINESS-LOGIC.md:207:| `quantity_on_hand` | Total physical stock count |
specs/05-BUSINESS-LOGIC.md:213:Per-variant policy stored in `inventory_items.policy`:
specs/05-BUSINESS-LOGIC.md:217:| `deny` | Block add-to-cart when available <= 0. Storefront displays "Out of stock". |
specs/05-BUSINESS-LOGIC.md:218:| `continue` | Allow add-to-cart regardless of stock level. When available <= 0, storefront displays "Available on backorder". |
specs/05-BUSINESS-LOGIC.md:232:        C -->|Restock on refund| A
specs/05-BUSINESS-LOGIC.md:243:| **Restock** | Refund processed with restock flag | +quantity | No change | None |
specs/05-BUSINESS-LOGIC.md:306:- Re-check inventory policy for the new quantity.
specs/05-BUSINESS-LOGIC.md:343:- Releases any reserved inventory associated with active checkouts for these carts.
specs/05-BUSINESS-LOGIC.md:433:    note right of completed : Order created, inventory committed
specs/05-BUSINESS-LOGIC.md:434:    note right of expired : Reserved inventory released
specs/05-BUSINESS-LOGIC.md:498:2. Reserve inventory for all cart lines (call InventoryService.reserve for each line).
specs/05-BUSINESS-LOGIC.md:521:           Release reserved inventory
specs/05-BUSINESS-LOGIC.md:531:           inventoryAction = 'commit'
specs/05-BUSINESS-LOGIC.md:536:           inventoryAction = 'keep_reserved'
specs/05-BUSINESS-LOGIC.md:557:    8. IF inventoryAction = 'commit':
specs/05-BUSINESS-LOGIC.md:560:       // Note: for bank_transfer, inventory stays reserved until admin confirms payment
specs/05-BUSINESS-LOGIC.md:569:    12. IF inventoryAction = 'commit' AND all order lines are digital:
specs/05-BUSINESS-LOGIC.md:585:1. If inventory was reserved (status was `payment_selected`): release all reserved inventory via InventoryService.release.
specs/05-BUSINESS-LOGIC.md:979:    Backend->>Backend: Reserve inventory (if not already reserved)
specs/05-BUSINESS-LOGIC.md:986:            Backend->>Backend: Commit inventory, mark cart converted
specs/05-BUSINESS-LOGIC.md:989:            Backend->>Backend: Release reserved inventory
specs/05-BUSINESS-LOGIC.md:1037:5. Backend calls `InventoryService.commit()` for each order line (converts reserved stock to committed).
specs/05-BUSINESS-LOGIC.md:1050:1. Release reserved inventory via `InventoryService.release()`.
specs/05-BUSINESS-LOGIC.md:1130:| `restock` | boolean | No | Whether to restock inventory for refunded items. |
specs/05-BUSINESS-LOGIC.md:1160:    7. IF request.restock = true:
specs/05-BUSINESS-LOGIC.md:1162:           CALL InventoryService.restock(variant, quantity)
specs/05-BUSINESS-LOGIC.md:1255:The fulfillment guard interacts with inventory differently depending on the payment method:
specs/05-BUSINESS-LOGIC.md:1259:| `credit_card` / `paypal` | Inventory committed (on_hand decremented, reserved decremented) | N/A (already committed) | No inventory change |
specs/05-BUSINESS-LOGIC.md:1260:| `bank_transfer` | Inventory reserved only (reserved incremented) | Inventory committed (on_hand decremented, reserved decremented) | No inventory change |
specs/05-BUSINESS-LOGIC.md:1262:For bank transfer orders, inventory is held in a reserved state until the admin confirms payment. If the order is auto-cancelled (see Section 10.8), the reserved inventory is released back.
specs/05-BUSINESS-LOGIC.md:1595:| `OrderRefunded` | Send refund notification email, dispatch webhooks (`order.refunded`), optionally restock |
specs/05-BUSINESS-LOGIC.md:1599:| `CheckoutExpired` | Release reserved inventory |
specs/05-BUSINESS-LOGIC.md:1604:| `OrderPaid` | Update order status, commit inventory (bank transfer confirmation), auto-fulfill digital products |
specs/05-BUSINESS-LOGIC.md:1608:| `OrderCancelled` | Release reserved inventory, send cancellation email |
specs/05-BUSINESS-LOGIC.md:1619:| `App\Jobs\ExpireAbandonedCheckouts` | Every 15 minutes | Expire checkouts idle for 24+ hours, release reserved inventory |
specs/05-BUSINESS-LOGIC.md:1640:| InventoryService | `App\Services` | Reserve, release, commit, restock operations |
specs/05-BUSINESS-LOGIC.md:1651:| RefundService | `App\Services` | Refund processing and inventory restock |
tests/Browser/SmokeTest.php:79:        '/admin/inventory' => 'Inventory',
tests/Feature/Orders/OrderServiceTest.php:57:function orderCompletionVariant(Store $store, int $price = 2500, int $stock = 10): ProductVariant
tests/Feature/Orders/OrderServiceTest.php:69:            'quantity_on_hand' => $stock,
tests/Feature/Orders/OrderServiceTest.php:119:    app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Orders/OrderServiceTest.php:145:test('checkout completion creates a paid order and commits inventory', function () {
tests/Feature/Orders/OrderServiceTest.php:179:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Orders/OrderServiceTest.php:181:    expect($inventory->quantity_on_hand)->toBe(8)
tests/Feature/Orders/OrderServiceTest.php:182:        ->and($inventory->quantity_reserved)->toBe(0);
tests/Feature/Orders/OrderServiceTest.php:268:test('bank transfer completion creates a pending order and keeps inventory reserved', function () {
tests/Feature/Orders/OrderServiceTest.php:281:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Orders/OrderServiceTest.php:283:    expect($inventory->quantity_on_hand)->toBe(10)
tests/Feature/Orders/OrderServiceTest.php:284:        ->and($inventory->quantity_reserved)->toBe(2);
tests/Feature/Orders/OrderServiceTest.php:290:test('payment failures release reserved inventory and allow checkout retry', function () {
tests/Feature/Orders/OrderServiceTest.php:298:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Orders/OrderServiceTest.php:301:        ->and($inventory->quantity_on_hand)->toBe(10)
tests/Feature/Orders/OrderServiceTest.php:302:        ->and($inventory->quantity_reserved)->toBe(0)
tests/Feature/Orders/BankTransferOrderTest.php:80:test('confirming bank transfer payment captures payment and commits reserved inventory', function () {
tests/Feature/Orders/BankTransferOrderTest.php:86:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Orders/BankTransferOrderTest.php:91:        ->and($inventory->quantity_on_hand)->toBe(8)
tests/Feature/Orders/BankTransferOrderTest.php:92:        ->and($inventory->quantity_reserved)->toBe(0);
tests/Feature/Orders/RefundServiceTest.php:70:test('refund service processes a partial line refund and restocks inventory', function () {
tests/Feature/Orders/RefundServiceTest.php:78:        'restock' => true,
tests/Feature/Storefront/CartCheckoutUiTest.php:50:test('product detail add to cart persists a session cart', function () {
tests/Feature/Storefront/CartCheckoutUiTest.php:70:    $line = app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Storefront/CartCheckoutUiTest.php:91:    app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Storefront/CartCheckoutUiTest.php:129:    app(CartService::class)->addLine($customerCart, $variant->getKey(), 1);
tests/Feature/Storefront/CartCheckoutUiTest.php:130:    app(CartService::class)->addLine($guestCart, $variant->getKey(), 2);
tests/Feature/Storefront/CartCheckoutUiTest.php:147:    app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Storefront/CartCheckoutUiTest.php:175:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Storefront/CartCheckoutUiTest.php:180:        ->and($inventory->quantity_reserved)->toBe(2);
tests/Feature/Admin/OrderManagementTest.php:170:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Admin/OrderManagementTest.php:175:        ->and($inventory->quantity_on_hand)->toBe(8)
tests/Feature/Admin/OrderManagementTest.php:176:        ->and($inventory->quantity_reserved)->toBe(0);
tests/Feature/Catalog/ProductServiceTest.php:32:test('product service creates products with a default variant and inventory', function () {
tests/Feature/Catalog/ProductServiceTest.php:45:        ->and($product->variants->first()->inventoryItem)->not->toBeNull();
tests/Feature/Storefront/OrderViewsTest.php:64:    app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Storefront/OrderViewsTest.php:98:    app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Storefront/OrderViewsTest.php:119:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Storefront/OrderViewsTest.php:123:        ->and($inventory->quantity_reserved)->toBe(0);
tests/Feature/Catalog/CatalogFoundationTest.php:23:        ->and(Schema::hasColumns('inventory_items', ['store_id', 'variant_id', 'quantity_on_hand', 'quantity_reserved', 'policy']))->toBeTrue()
tests/Feature/Catalog/CatalogFoundationTest.php:33:        ->and(Product::withoutGlobalScopes()->where('handle', 'limited-edition-sneakers')->first()?->variants()->withoutGlobalScopes()->first()?->inventoryItem?->policy?->value)->toBe('deny')
tests/Feature/Catalog/CatalogFoundationTest.php:34:        ->and(Product::withoutGlobalScopes()->where('handle', 'backorder-denim-jacket')->first()?->variants()->withoutGlobalScopes()->first()?->inventoryItem?->policy?->value)->toBe('continue');
tests/Feature/Catalog/CatalogFoundationTest.php:72:test('variants create inventory for their product store regardless of resolved store scope', function () {
tests/Feature/Catalog/CatalogFoundationTest.php:80:    $inventory = InventoryItem::withoutGlobalScopes()
tests/Feature/Catalog/CatalogFoundationTest.php:84:    expect($inventory)->not->toBeNull()
tests/Feature/Catalog/CatalogFoundationTest.php:85:        ->and($inventory->store_id)->toBe($productStore->getKey())
tests/Feature/Catalog/CatalogFoundationTest.php:86:        ->and($inventory->policy)->toBe(InventoryPolicy::Deny);
tests/Feature/Catalog/CatalogFoundationTest.php:89:test('inventory store must match the variant product store', function () {
tests/Feature/Checkout/PricingServicesTest.php:73:    app(CartService::class)->addLine($cart, $variant->getKey(), $quantity);
tests/Feature/Checkout/PricingServicesTest.php:235:    app(CartService::class)->addLine($usedCart, $variant->getKey(), 1);
tests/Feature/Checkout/PricingServicesTest.php:246:    app(CartService::class)->addLine($otherCart, $variant->getKey(), 1);
tests/Feature/Checkout/PricingServicesTest.php:256:    app(CartService::class)->addLine($cart, $physicalVariant->getKey(), 2);
tests/Feature/Checkout/PricingServicesTest.php:257:    app(CartService::class)->addLine($cart, $digitalVariant->getKey(), 1);
tests/Feature/Catalog/InventoryServiceTest.php:12:test('inventory reserve release commit and restock update quantities transactionally', function () {
tests/Feature/Catalog/InventoryServiceTest.php:18:    $item = $variant->inventoryItem()->firstOrFail();
tests/Feature/Catalog/InventoryServiceTest.php:33:    $service->restock($item, 5);
tests/Feature/Catalog/InventoryServiceTest.php:37:test('deny policy blocks reservations above available stock while continue allows it', function () {
tests/Feature/Catalog/InventoryServiceTest.php:43:    $denyItem = $denyVariant->inventoryItem()->firstOrFail();
tests/Feature/Catalog/InventoryServiceTest.php:51:    $continueItem = $continueVariant->inventoryItem()->firstOrFail();
tests/Feature/Api/StorefrontCheckoutApiTest.php:138:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Api/StorefrontCheckoutApiTest.php:141:        ->and($inventory->quantity_reserved)->toBe(2);
tests/Feature/Catalog/CatalogUiTest.php:73:        ->get('/admin/inventory')
tests/Feature/Catalog/CatalogUiTest.php:100:        ->and($product->variants()->first()?->inventoryItem?->quantity_on_hand)->toBe(50);
tests/Feature/Admin/SettingsManagementTest.php:199:        ->and(data_get($settings, 'notifications.low_stock_alerts_enabled'))->toBeTrue()
tests/Feature/Admin/SettingsManagementTest.php:200:        ->and(data_get($settings, 'notifications.low_stock_threshold'))->toBe(3);
tests/Feature/Checkout/CheckoutServiceTest.php:92:    app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Checkout/CheckoutServiceTest.php:126:    app(CartService::class)->addLine($cart, $variant->getKey(), 1);
tests/Feature/Checkout/CheckoutServiceTest.php:138:    app(CartService::class)->addLine($cart, $variant->getKey(), 1);
tests/Feature/Checkout/CheckoutServiceTest.php:165:    app(CartService::class)->addLine($cart, $variant->getKey(), 2);
tests/Feature/Checkout/CheckoutServiceTest.php:195:    app(CartService::class)->addLine($cart, $variant->getKey(), 1);
tests/Feature/Api/StorefrontSearchApiTest.php:52:        'in_stock' => true,
tests/Feature/Api/StorefrontOrderApiTest.php:142:    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
tests/Feature/Api/StorefrontOrderApiTest.php:145:        ->and($inventory->quantity_reserved)->toBe(0);
tests/Feature/Catalog/VariantMatrixServiceTest.php:13:test('variant matrix rebuild creates missing cartesian combinations and inventory', function () {
tests/Feature/Catalog/VariantMatrixServiceTest.php:38:        ->and($product->variants()->whereHas('inventoryItem')->count())->toBe(4);
tests/Feature/Catalog/VariantMatrixServiceTest.php:65:        ->and($product->variants()->first()->inventoryItem)->not->toBeNull();
tests/Feature/Api/AdminStoreSettingsApiTest.php:109:                    'low_stock_threshold' => 12,
tests/Feature/Api/AdminStoreSettingsApiTest.php:114:        ->assertJsonPath('data.settings_json.notifications.low_stock_threshold', 12);
tests/Feature/Api/AdminCatalogApiTest.php:69:        ->assertJsonPath('data.0.total_inventory', 50)
tests/Feature/Api/AdminCatalogApiTest.php:77:        ->assertJsonPath('data.variants.0.inventory.quantity_on_hand', 50);
tests/Feature/Cart/CartServiceTest.php:27:function cartServiceVariant(Store $store, int $price = 2500, int $stock = 20, InventoryPolicy $policy = InventoryPolicy::Deny): ProductVariant
tests/Feature/Cart/CartServiceTest.php:39:            'quantity_on_hand' => $stock,
tests/Feature/Cart/CartServiceTest.php:49:    $variant = cartServiceVariant($store, price: 2500, stock: 20);
tests/Feature/Cart/CartServiceTest.php:57:    $line = $service->addLine($cart, $variant->getKey(), 2, expectedVersion: 1);
tests/Feature/Cart/CartServiceTest.php:64:    $service->addLine($cart, $variant->getKey(), 1, expectedVersion: 2);
tests/Feature/Cart/CartServiceTest.php:83:test('cart service rejects stale versions inactive products and insufficient stock', function () {
tests/Feature/Cart/CartServiceTest.php:85:    $variant = cartServiceVariant($store, stock: 2);
tests/Feature/Cart/CartServiceTest.php:89:    expect(fn () => $service->addLine($cart, $variant->getKey(), 1, expectedVersion: 99))
tests/Feature/Cart/CartServiceTest.php:100:    expect(fn () => $service->addLine($cart, $draftVariant->getKey(), 1))
tests/Feature/Cart/CartServiceTest.php:103:    expect(fn () => $service->addLine($cart, $variant->getKey(), 5))
tests/Feature/Cart/CartServiceTest.php:109:    $firstVariant = cartServiceVariant($store, stock: 0, policy: InventoryPolicy::Continue);
tests/Feature/Cart/CartServiceTest.php:110:    $secondVariant = cartServiceVariant($store, stock: 10);
tests/Feature/Cart/CartServiceTest.php:116:    $service->addLine($guestCart, $firstVariant->getKey(), 5);
tests/Feature/Cart/CartServiceTest.php:117:    $service->addLine($customerCart, $firstVariant->getKey(), 2);
tests/Feature/Cart/CartServiceTest.php:118:    $service->addLine($customerCart, $secondVariant->getKey(), 3);
tests/Feature/Api/AdminShippingSettingsApiTest.php:52:            'regions_json' => ['stockholm'],
resources/views/layouts/app/sidebar.blade.php:43:                    <flux:sidebar.item icon="archive-box" :href="route('admin.inventory.index')" :current="request()->routeIs('admin.inventory.*')" wire:navigate>
resources/views/components/storefront/product-card.blade.php:6:        && $product->variants->every(fn ($variant) => $variant->inventoryItem?->policy?->value === 'deny' && $variant->inventoryItem?->availableQuantity() <= 0);
resources/views/livewire/admin/inventory/index.blade.php:4:        <flux:text class="mt-1">Review stock levels by product variant.</flux:text>
resources/views/livewire/admin/inventory/index.blade.php:8:        <flux:input wire:model.live.debounce.300ms="search" icon="magnifying-glass" placeholder="Search by product or SKU..." aria-label="Search inventory" />
resources/views/livewire/admin/inventory/index.blade.php:10:        <flux:select wire:model.live="stockFilter" aria-label="Stock filter">
resources/views/livewire/admin/inventory/index.blade.php:11:            <flux:select.option value="all">All stock</flux:select.option>
resources/views/livewire/admin/inventory/index.blade.php:12:            <flux:select.option value="low">Low stock</flux:select.option>
resources/views/livewire/admin/inventory/index.blade.php:13:            <flux:select.option value="out">Out of stock</flux:select.option>
resources/views/livewire/admin/inventory/index.blade.php:32:
getKey() }}">
resources/views/livewire/admin/inventory/index.blade.php:48:                            No inventory items found.
app/Services/SearchService.php:319:        if (filter_var($filters['in_stock'] ?? false, FILTER_VALIDATE_BOOL)) {
app/Services/SearchService.php:324:                    ->join('inventory_items', 'inventory_items.variant_id', '=', 'product_variants.id')
app/Services/SearchService.php:328:                            ->whereRaw('inventory_items.quantity_on_hand > inventory_items.quantity_reserved')
app/Services/SearchService.php:329:                            ->orWhere('inventory_items.policy', InventoryPolicy::Continue->value);
app/Services/SearchService.php:368:            ->with(['store', 'variants.inventoryItem', 'media'])
resources/views/livewire/admin/products/index.blade.php:5:            <flux:text class="mt-1">Manage catalog items, variants, status, and inventory.</flux:text>
resources/views/livewire/admin/products/index.blade.php:64:                            $inventory = $product->variants->sum(fn ($variant) => $variant->inventoryItem?->quantity_on_hand ?? 0);
resources/views/livewire/admin/products/index.blade.php:93:                            {{ $inventory }}
app/Http/Controllers/Api/Admin/V1/OrderRefundController.php:25:            'restock' => (bool) $request->validated('restock', false),
app/Services/ThemeSettingsService.php:69:                    'subheading' => 'Browse a scoped demo catalog with variants, inventory states, sale pricing, and digital products.',
resources/views/livewire/admin/settings/notifications.blade.php:61:                    <flux:switch wire:model="lowStockAlertsEnabled" label="Low stock alerts" align="left" />
resources/views/livewire/admin/settings/notifications.blade.php:62:                    <flux:input wire:model="lowStockThreshold" type="number" min="0" max="999" label="Low stock threshold" />
app/Http/Controllers/Api/Admin/V1/StoreSettingsController.php:56:            'settings_json.notifications.low_stock_alerts_enabled' => ['sometimes', 'boolean'],
app/Http/Controllers/Api/Admin/V1/StoreSettingsController.php:57:            'settings_json.notifications.low_stock_threshold' => ['sometimes', 'integer', 'min:0', 'max:1000'],
app/Http/Controllers/Api/Storefront/V1/CartLineController.php:23:            $carts->addLine(
app/Http/Controllers/Api/Admin/V1/ProductController.php:31:                'variants.inventoryItem',
app/Http/Controllers/Api/Admin/V1/ProductController.php:83:            'variants.inventoryItem',
app/Services/CartService.php:21:        private readonly InventoryService $inventory,
app/Services/CartService.php:120:    public function addLine(Cart $cart, int $variantId, int $quantity, ?int $expectedVersion = null): CartLine
app/Services/CartService.php:136:            $this->assertAvailable($variant->inventoryItem, $newQuantity);
app/Services/CartService.php:172:            $this->assertAvailable($variant->inventoryItem, $quantity);
app/Services/CartService.php:244:                'inventoryItem' => fn ($query) => $query->withoutGlobalScopes(),
app/Services/CartService.php:260:        if (! $variant->inventoryItem instanceof InventoryItem) {
app/Services/CartService.php:261:            throw InvalidCartOperationException::because('Variant inventory is missing.');
app/Services/CartService.php:269:        if (! $this->inventory->checkAvailability($item, $quantity)) {
app/Http/Requests/Api/Admin/V1/CreateOrderRefundRequest.php:22:            'restock' => ['sometimes', 'boolean'],
app/Services/CheckoutService.php:22:        private readonly InventoryService $inventory,
app/Services/CheckoutService.php:149:                    $inventory = InventoryItem::withoutGlobalScopes()
app/Services/CheckoutService.php:153:                    $this->inventory->reserve($inventory, $line->quantity);
app/Services/CheckoutService.php:180:                        $inventory = InventoryItem::withoutGlobalScopes()
app/Services/CheckoutService.php:184:                        $this->inventory->release($inventory, $line->quantity);
app/Services/OrderService.php:36:        private readonly InventoryService $inventory,
app/Services/OrderService.php:358:            $this->inventory->commit($this->inventoryItemForVariant($line->variant_id), $line->quantity);
app/Services/OrderService.php:366:                $this->inventory->commit($this->inventoryItemForVariant($line->variant_id), $line->quantity);
app/Services/OrderService.php:375:                $this->inventory->release($this->inventoryItemForVariant($line->variant_id), $line->quantity);
app/Services/OrderService.php:390:                $this->inventory->release($this->inventoryItemForVariant($line->variant_id), $line->quantity);
app/Services/OrderService.php:422:    private function inventoryItemForVariant(int $variantId): InventoryItem
resources/views/livewire/storefront/collections/show.blade.php:22:                <flux:checkbox wire:model.live="inStock" label="In stock" />
resources/views/livewire/storefront/search/index.blade.php:24:                <flux:checkbox wire:model.live="inStock" label="In stock" />
app/Services/ProductService.php:184:                'policy' => $variantData['inventory_policy'] ?? 'deny',
resources/views/livewire/storefront/products/show.blade.php:61:
{{ $stockState['message'] }}

app/Services/RefundService.php:23:        private readonly InventoryService $inventory,
app/Services/RefundService.php:27:     * @param  array{amount?: int, lines?: array<int|string, int>, reason?: string|null, restock?: bool}  $request
app/Services/RefundService.php:52:            if ((bool) data_get($request, 'restock', false)) {
app/Services/RefundService.php:53:                $this->restock($order, $lineQuantities);
app/Services/RefundService.php:161:    private function restock(Order $order, Collection $lineQuantities): void
app/Services/RefundService.php:163:        $linesToRestock = $lineQuantities->isNotEmpty()
app/Services/RefundService.php:167:        $linesToRestock->each(function (int $quantity, int $lineId) use ($order): void {
app/Services/RefundService.php:179:                $this->inventory->restock($item, $quantity);
app/Services/InventoryService.php:49:                throw new InvalidArgumentException('Cannot release more inventory than is reserved.');
app/Services/InventoryService.php:66:                throw new InvalidArgumentException('Cannot commit more inventory than is reserved.');
app/Services/InventoryService.php:76:    public function restock(InventoryItem $item, int $quantity): void
app/Http/Resources/Admin/V1/ProductResource.php:31:            'total_inventory' => $this->when($this->relationLoaded('variants'), fn (): int => $this->variants->sum(
app/Http/Resources/Admin/V1/ProductResource.php:32:                fn (ProductVariant $variant): int => $variant->inventoryItem?->quantity_on_hand ?? 0,
app/Http/Resources/Admin/V1/ProductResource.php:67:                    'inventory' => [
app/Http/Resources/Admin/V1/ProductResource.php:68:                        'quantity_on_hand' => $variant->inventoryItem?->quantity_on_hand ?? 0,
app/Http/Resources/Admin/V1/ProductResource.php:69:                        'quantity_reserved' => $variant->inventoryItem?->quantity_reserved ?? 0,
app/Http/Resources/Admin/V1/ProductResource.php:70:                        'policy' => $variant->inventoryItem?->policy?->value,
app/Http/Requests/Api/Storefront/V1/SearchProductsRequest.php:26:            'filters.in_stock' => ['nullable', 'boolean'],
app/Models/ProductVariant.php:74:            if ($variant->inventoryItem()->exists()) {
app/Models/ProductVariant.php:140:    public function inventoryItem(): HasOne
app/Http/Resources/Storefront/V1/SearchProductResource.php:33:            'in_stock' => $variant instanceof ProductVariant ? $this->variantIsInStock($variant) : false,
app/Http/Resources/Storefront/V1/SearchProductResource.php:40:        $inventory = $variant->inventoryItem;
app/Http/Resources/Storefront/V1/SearchProductResource.php:42:        if ($inventory === null) {
app/Http/Resources/Storefront/V1/SearchProductResource.php:46:        return $inventory->availableQuantity() > 0
app/Http/Resources/Storefront/V1/SearchProductResource.php:47:            || $inventory->policy === InventoryPolicy::Continue;
app/Livewire/Admin/Inventory/Index.php:17:    public string $stockFilter = 'all';
app/Livewire/Admin/Inventory/Index.php:42:            ->when($this->stockFilter === 'low', fn (Builder $query) => $query->whereRaw('(quantity_on_hand - quantity_reserved) BETWEEN 1 AND 10'))
app/Livewire/Admin/Inventory/Index.php:43:            ->when($this->stockFilter === 'out', fn (Builder $query) => $query->whereRaw('(quantity_on_hand - quantity_reserved) <= 0'))
app/Livewire/Admin/Inventory/Index.php:50:        return view('livewire.admin.inventory.index', [
app/Livewire/Admin/Settings/Notifications.php:75:                    'low_stock_alerts_enabled' => $validated['lowStockAlertsEnabled'],
app/Livewire/Admin/Settings/Notifications.php:76:                    'low_stock_threshold' => $validated['lowStockThreshold'],
app/Livewire/Admin/Settings/Notifications.php:106:        $this->lowStockAlertsEnabled = (bool) data_get($settings, 'notifications.low_stock_alerts_enabled', true);
app/Livewire/Admin/Settings/Notifications.php:107:        $this->lowStockThreshold = (int) data_get($settings, 'notifications.low_stock_threshold', 5);
app/Livewire/Storefront/Collections/Show.php:70:            ->with(['variants.inventoryItem'])
app/Livewire/Storefront/Collections/Show.php:75:                $query->whereHas('variants.inventoryItem', function (Builder $query): void {
app/Livewire/Admin/Products/Form.php:82:            $this->product = $product->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Admin/Products/Form.php:232:        $this->product = $product->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Admin/Products/Form.php:250:        $this->product = $product->refresh()->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Admin/Products/Form.php:403:                'quantity' => $variant->inventoryItem?->quantity_on_hand ?? 0,
app/Livewire/Admin/Products/Form.php:800:        $this->product = $this->productForAction()->load(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections', 'media']);
app/Livewire/Storefront/Search/Index.php:110:            'in_stock' => $this->inStock,
app/Livewire/Storefront/Home.php:26:            ->with(['variants.inventoryItem'])
app/Livewire/Storefront/Products/Show.php:52:        $max = $variant?->inventoryItem?->policy === InventoryPolicy::Deny
app/Livewire/Storefront/Products/Show.php:53:            ? max(1, $variant->inventoryItem->availableQuantity())
app/Livewire/Storefront/Products/Show.php:78:        app(CartService::class)->addLine(
app/Livewire/Storefront/Products/Show.php:109:            ->with(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections'])
app/Livewire/Storefront/Products/Show.php:141:        $inventory = $variant->inventoryItem;
app/Livewire/Storefront/Products/Show.php:143:        return $inventory?->policy === InventoryPolicy::Continue
app/Livewire/Storefront/Products/Show.php:144:            || ($inventory?->availableQuantity() ?? 0) >= $this->quantity;
app/Livewire/Storefront/Products/Show.php:150:    public function stockState(): array
app/Livewire/Storefront/Products/Show.php:153:        $inventory = $variant?->inventoryItem;
app/Livewire/Storefront/Products/Show.php:155:        if (! $inventory) {
app/Livewire/Storefront/Products/Show.php:159:        if ($inventory->policy === InventoryPolicy::Continue && $inventory->availableQuantity() <= 0) {
app/Livewire/Storefront/Products/Show.php:160:            return ['message' => 'Available on backorder', 'class' => 'text-blue-700 dark:text-blue-300'];
app/Livewire/Storefront/Products/Show.php:163:        if ($inventory->availableQuantity() <= 0) {
app/Livewire/Storefront/Products/Show.php:164:            return ['message' => 'Out of stock', 'class' => 'text-red-700 dark:text-red-300'];
app/Livewire/Storefront/Products/Show.php:167:        if ($inventory->availableQuantity() <= 10) {
app/Livewire/Storefront/Products/Show.php:168:            return ['message' => "Only {$inventory->availableQuantity()} left in stock", 'class' => 'text-amber-700 dark:text-amber-300'];
app/Livewire/Storefront/Products/Show.php:171:        return ['message' => 'In stock', 'class' => 'text-green-700 dark:text-green-300'];
app/Livewire/Storefront/Products/Show.php:181:            'stockState' => $this->stockState(),
app/Livewire/Admin/Products/Index.php:93:            ->with(['variants.inventoryItem'])


message: Suite 11 mostly matches existing behavior: Suite 7 already checks the out-of-stock and backorder messaging, but Suite 11 adds a stock-limit quantity interaction. I’m reading the product/cart components to see whether the browser suite can cover the existing controls or whether the UI needs a customer-facing stock error.

phase: commentary


type: message

role: assistant

text: Suite 11 mostly matches existing behavior: Suite 7 already checks the out-of-stock and backorder messaging, but Suite 11 adds a stock-limit quantity interaction. I’m reading the product/cart components to see whether the browser suite can cover the existing controls or whether the UI needs a customer-facing stock error.


cmd: sed -n '1,260p' app/Livewire/Storefront/Products/Show.php


cmd: sed -n '1,320p' resources/views/livewire/storefront/products/show.blade.php


cmd: sed -n '1,320p' app/Livewire/Storefront/Cart/Show.php


cmd: sed -n '1,360p' resources/views/livewire/storefront/cart/show.blade.php


command: sed -n '1,320p' resources/views/livewire/storefront/products/show.blade.php

show.blade.php

type: read

aggregated_output:
    <x-storefront.breadcrumbs :items="[
        ['label' => $product->collections->first()?->title ?? 'Products', 'url' => $product->collections->first() ? route('collections.show', $product->collections->first()->handle) : route('collections.index')],
        ['label' => $product->title],
    ]" />

                <flux:icon name="shopping-bag" class="size-20" />

                    @if ($selectedVariant?->compare_at_amount && $selectedVariant->compare_at_amount > $selectedVariant->price_amount)
                        Sale
                    @endif
                    @foreach ($product->tags ?? [] as $tag)
                        {{ $tag }}
                    @endforeach

{{ $product->title }}

                @if ($selectedVariant)
                    <x-storefront.price :amount="$selectedVariant->price_amount" :compare-at="$selectedVariant->compare_at_amount" :currency="$selectedVariant->currency" class="text-2xl" aria-live="polite" />
                @endif

            @if ($product->options->isNotEmpty())

                    @foreach ($product->options as $option)
                        <fieldset class="space-y-3" wire:key="product-option-selector-{{ $option->getKey() }}">
                            <legend class="text-sm font-medium text-zinc-950 dark:text-white">{{ $option->name }}</legend>

                                @foreach ($option->values as $value)
                                    @php($selected = ($selectedOptions[$option->name] ?? null) === $value->value)
                                    <button
                                        type="button"
                                        wire:click="selectOption(@js($option->name), @js($value->value))"
                                        @class([
                                            'min-h-10 rounded-md border px-4 py-2 text-sm font-medium transition',
                                            'border-blue-700 bg-blue-50 text-blue-800 dark:border-blue-300 dark:bg-blue-950 dark:text-blue-100' => $selected,
                                            'border-zinc-200 text-zinc-700 hover:border-zinc-400 dark:border-zinc-700 dark:text-zinc-200 dark:hover:border-zinc-500' => ! $selected,
                                        ])
                                        aria-pressed="{{ $selected ? 'true' : 'false' }}"
                                    >
                                        {{ $value->value }}
                                    </button>
                                @endforeach

                        </fieldset>
                    @endforeach

            @endif

{{ $stockState['message'] }}

                    <button type="button" wire:click="decreaseQuantity" class="flex size-11 items-center justify-center border-r border-zinc-200 text-lg dark:border-zinc-700" aria-label="Decrease quantity">-</button>
                    <input wire:model.live="quantity" type="number" min="1" class="h-11 w-full border-0 bg-transparent text-center text-sm" aria-label="Quantity">
                    <button type="button" wire:click="increaseQuantity" class="flex size-11 items-center justify-center border-l border-zinc-200 text-lg dark:border-zinc-700" aria-label="Increase quantity">+</button>

                <flux:button wire:click="addToCart" variant="primary" class="w-full" :disabled="! $this->canAddToCart()">
                    {{ $this->canAddToCart() ? 'Add to cart' : 'Sold out' }}
                </flux:button>

            @if ($product->description_html)

                    {!! $product->description_html !!}

            @endif

Vendor

{{ $product->vendor ?: '-' }}

Product type

{{ $product->product_type ?: '-' }}

                @if ($selectedVariant)

SKU

{{ $selectedVariant->sku ?: '-' }}

Shipping

{{ $selectedVariant->requires_shipping ? 'Required' : 'Digital delivery' }}

                @endif


cmd: sed -n '1,340p' app/Services/CartService.php


command: sed -n '1,260p' app/Livewire/Storefront/Products/Show.php

aggregated_output:
<?php

namespace App\Livewire\Storefront\Products;

use App\Enums\InventoryPolicy;
use App\Models\Customer;
use App\Models\Product;
use App\Models\ProductOptionValue;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Services\CartService;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;

class Show extends Component
{
    public string $handle;

    public int $storeId;

    /**
     * @var array<string, string>
     */
    public array $selectedOptions = [];

    public int $quantity = 1;

    public function mount(string $handle): void
    {
        $this->handle = $handle;
        $this->storeId = $this->store()->getKey();

        $variant = $this->product()->variants->firstWhere('is_default', true)
            ?? $this->product()->variants->first();

        if ($variant instanceof ProductVariant) {
            $this->selectedOptions = $variant->optionValues
                ->mapWithKeys(fn (ProductOptionValue $value): array => [$value->option->name => $value->value])
                ->all();
        }
    }

    public function selectOption(string $optionName, string $value): void
    {
        $this->selectedOptions[$optionName] = $value;
        $this->quantity = 1;
    }

    public function increaseQuantity(): void
    {
        $variant = $this->selectedVariant();
        $max = $variant?->inventoryItem?->policy === InventoryPolicy::Deny
            ? max(1, $variant->inventoryItem->availableQuantity())
            : null;

        if ($max === null || $this->quantity < $max) {
            $this->quantity++;
        }
    }

    public function decreaseQuantity(): void
    {
        $this->quantity = max(1, $this->quantity - 1);
    }

    public function addToCart(): void
    {
        $store = $this->store();
        $variant = $this->selectedVariant();

        if (! $variant instanceof ProductVariant || ! $this->canAddToCart()) {
            return;
        }

        $customer = Auth::guard('customer')->user();
        $customer = $customer instanceof Customer ? $customer : null;

        app(CartService::class)->addLine(
            app(CartService::class)->getOrCreateForSession($store, $customer),
            $variant->getKey(),
            $this->quantity,
        );

        $this->dispatch('cart-updated');
        $this->dispatch('toast', type: 'success', message: __('Added to cart'));
    }

    public function store(): Store
    {
        if (isset($this->storeId)) {
            $store = Store::query()->findOrFail($this->storeId);
            app()->instance('current_store', $store);

            return $store;
        }

        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        return $store;
    }

    public function product(): Product
    {
        $this->store();

        return Product::query()
            ->with(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections'])
            ->where('handle', $this->handle)
            ->where('status', 'active')
            ->whereNotNull('published_at')
            ->firstOrFail();
    }

    public function selectedVariant(): ?ProductVariant
    {
        $product = $this->product();

        if ($product->options->isEmpty()) {
            return $product->variants->first();
        }

        return $product->variants->first(function (ProductVariant $variant): bool {
            $options = $variant->optionValues
                ->mapWithKeys(fn (ProductOptionValue $value): array => [$value->option->name => $value->value])
                ->all();

            return $options === $this->selectedOptions;
        });
    }

    public function canAddToCart(): bool
    {
        $variant = $this->selectedVariant();

        if (! $variant instanceof ProductVariant || ! $variant->isPurchasable()) {
            return false;
        }

        $inventory = $variant->inventoryItem;

        return $inventory?->policy === InventoryPolicy::Continue
            || ($inventory?->availableQuantity() ?? 0) >= $this->quantity;
    }

    /**
     * @return array{message: string, class: string}
     */
    public function stockState(): array
    {
        $variant = $this->selectedVariant();
        $inventory = $variant?->inventoryItem;

        if (! $inventory) {
            return ['message' => 'Unavailable', 'class' => 'text-red-700 dark:text-red-300'];
        }

        if ($inventory->policy === InventoryPolicy::Continue && $inventory->availableQuantity() <= 0) {
            return ['message' => 'Available on backorder', 'class' => 'text-blue-700 dark:text-blue-300'];
        }

        if ($inventory->availableQuantity() <= 0) {
            return ['message' => 'Out of stock', 'class' => 'text-red-700 dark:text-red-300'];
        }

        if ($inventory->availableQuantity() <= 10) {
            return ['message' => "Only {$inventory->availableQuantity()} left in stock", 'class' => 'text-amber-700 dark:text-amber-300'];
        }

        return ['message' => 'In stock', 'class' => 'text-green-700 dark:text-green-300'];
    }

    public function render(): mixed
    {
        $product = $this->product();

        return view('livewire.storefront.products.show', [
            'product' => $product,
            'selectedVariant' => $this->selectedVariant(),
            'stockState' => $this->stockState(),
        ])->layout('layouts.storefront', [
            'title' => $product->title,
        ]);
    }
}


command: sed -n '1,320p' app/Livewire/Storefront/Cart/Show.php

aggregated_output:
<?php

namespace App\Livewire\Storefront\Cart;

use App\Exceptions\InvalidDiscountException;
use App\Models\Cart;
use App\Models\CartLine;
use App\Models\Customer;
use App\Models\ShippingRate;
use App\Models\Store;
use App\Services\CartService;
use App\Services\DiscountService;
use App\Services\ShippingCalculator;
use App\ValueObjects\DiscountResult;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\On;
use Livewire\Component;

class Show extends Component
{
    public int $storeId;

    public string $discountCode = '';

    public ?string $appliedDiscountCode = null;

    public string $shippingCountry = 'DE';

    public string $shippingPostalCode = '';

    public string $shippingProvinceCode = '';

    public function mount(): void
    {
        $this->storeId = $this->store()->getKey();
        $this->appliedDiscountCode = trim((string) session('cart_discount_code')) ?: null;
        $this->discountCode = $this->appliedDiscountCode ?? '';
    }

    #[On('cart-updated')]
    public function refreshCart(): void {}

    public function increaseQuantity(int $lineId): void
    {
        $line = $this->cartLine($lineId);

        if (! $line instanceof CartLine) {
            return;
        }

        app(CartService::class)->updateLineQuantity($line->cart, $line->getKey(), $line->quantity + 1);
        $this->dispatch('cart-updated');
    }

    public function decreaseQuantity(int $lineId): void
    {
        $line = $this->cartLine($lineId);

        if (! $line instanceof CartLine) {
            return;
        }

        app(CartService::class)->updateLineQuantity($line->cart, $line->getKey(), $line->quantity - 1);
        $this->dispatch('cart-updated');
    }

    public function removeLine(int $lineId): void
    {
        $line = $this->cartLine($lineId);

        if (! $line instanceof CartLine) {
            return;
        }

        app(CartService::class)->removeLine($line->cart, $line->getKey());
        $this->dispatch('cart-updated');
    }

    public function applyDiscount(): void
    {
        $this->validate([
            'discountCode' => ['required', 'string', 'max:50'],
        ]);

        $cart = $this->cart();

        if (! $cart instanceof Cart) {
            return;
        }

        $code = trim($this->discountCode);

        try {
            $discount = app(DiscountService::class)->validate($code, $this->store(), $cart);
            app(DiscountService::class)->calculate($discount, $this->subtotal(), $this->lines()->all());
        } catch (InvalidDiscountException $exception) {
            $this->removeDiscount();

            throw ValidationException::withMessages([
                'discountCode' => $exception->getMessage(),
            ]);
        }

        $this->appliedDiscountCode = $code;
        $this->discountCode = $code;
        session(['cart_discount_code' => $code]);
        $this->resetErrorBag('discountCode');
    }

    public function removeDiscount(): void
    {
        $this->appliedDiscountCode = null;
        $this->discountCode = '';
        session()->forget('cart_discount_code');
        $this->resetErrorBag('discountCode');
    }

    public function estimateShipping(): void
    {
        $this->validate([
            'shippingCountry' => ['required', 'string', 'size:2'],
            'shippingPostalCode' => ['nullable', 'string', 'max:20'],
            'shippingProvinceCode' => ['nullable', 'string', 'max:20'],
        ]);

        $this->resetErrorBag('shippingCountry');
    }

    public function checkout(): void
    {
        if ($this->lineCount() === 0) {
            return;
        }

        $this->redirectRoute('checkout.show', navigate: true);
    }

    public function store(): Store
    {
        if (isset($this->storeId)) {
            $store = Store::query()->findOrFail($this->storeId);
            app()->instance('current_store', $store);

            return $store;
        }

        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        return $store;
    }

    public function cart(): ?Cart
    {
        $cart = app(CartService::class)->currentForSession($this->store(), $this->customer());

        return $cart?->load([
            'lines.variant.product',
            'lines.variant.optionValues.option',
        ]);
    }

    /**
     * @return Collection<int, CartLine>
     */
    public function lines(): Collection
    {
        return $this->cart()?->lines->sortBy('id')->values() ?? collect();
    }

    public function lineCount(): int
    {
        return $this->lines()->sum('quantity');
    }

    public function subtotal(): int
    {
        return $this->lines()->sum('line_subtotal_amount');
    }

    /**
     * @return Collection<int, ShippingRate>
     */
    public function availableRates(): Collection
    {
        if (! $this->requiresShipping() || $this->shippingCountry === '') {
            return collect();
        }

        return app(ShippingCalculator::class)->getAvailableRates($this->store(), $this->shippingAddress());
    }

    public function requiresShipping(): bool
    {
        $cart = $this->cart();

        return $cart instanceof Cart && app(ShippingCalculator::class)->requiresShipping($cart);
    }

    /**
     * @return array<int, int>
     */
    public function shippingRateAmounts(): array
    {
        $cart = $this->cart();

        if (! $cart instanceof Cart) {
            return [];
        }

        return $this->availableRates()
            ->mapWithKeys(fn (ShippingRate $rate): array => [
                $rate->getKey() => app(ShippingCalculator::class)->calculate($rate, $cart) ?? 0,
            ])
            ->all();
    }

    public function estimatedShippingAmount(): ?int
    {
        if (! $this->requiresShipping()) {
            return 0;
        }

        $amounts = $this->shippingRateAmounts();

        return $amounts === [] ? null : min($amounts);
    }

    public function discountResult(): ?DiscountResult
    {
        $cart = $this->cart();
        $code = trim((string) $this->appliedDiscountCode);

        if (! $cart instanceof Cart || $code === '') {
            return null;
        }

        try {
            $discount = app(DiscountService::class)->validate($code, $this->store(), $cart);

            return app(DiscountService::class)->calculate($discount, $this->subtotal(), $this->lines()->all());
        } catch (InvalidDiscountException) {
            return null;
        }
    }

    public function discountAmount(): int
    {
        return $this->discountResult()?->amount ?? 0;
    }

    public function discountFreeShipping(): bool
    {
        return $this->discountResult()?->freeShipping ?? false;
    }

    public function estimatedTotal(): int
    {
        $shipping = $this->discountFreeShipping() ? 0 : ($this->estimatedShippingAmount() ?? 0);

        return max(0, $this->subtotal() - $this->discountAmount() + $shipping);
    }

    public function render(): mixed
    {
        return view('livewire.storefront.cart.show', [
            'cart' => $this->cart(),
            'lines' => $this->lines(),
            'lineCount' => $this->lineCount(),
            'subtotal' => $this->subtotal(),
            'discountAmount' => $this->discountAmount(),
            'discountFreeShipping' => $this->discountFreeShipping(),
            'rates' => $this->availableRates(),
            'rateAmounts' => $this->shippingRateAmounts(),
            'estimatedShipping' => $this->estimatedShippingAmount(),
            'estimatedTotal' => $this->estimatedTotal(),
            'requiresShipping' => $this->requiresShipping(),
        ])->layout('layouts.storefront', [
            'title' => 'Cart',
        ]);
    }

    private function customer(): ?Customer
    {
        $customer = Auth::guard('customer')->user();

        return $customer instanceof Customer ? $customer : null;
    }

    private function cartLine(int $lineId): ?CartLine
    {
        return $this->lines()->firstWhere('id', $lineId);
    }

    /**
     * @return array<string, string>
     */
    private function shippingAddress(): array
    {
        return [
            'country' => strtoupper($this->shippingCountry),
            'country_code' => strtoupper($this->shippingCountry),
            'postal_code' => $this->shippingPostalCode,
            'province_code' => strtoupper($this->shippingProvinceCode),
        ];
    }
}


command: sed -n '1,360p' resources/views/livewire/storefront/cart/show.blade.php

aggregated_output:
    <x-storefront.breadcrumbs :items="[['label' => 'Cart']]" />

Your Cart

{{ $lineCount }} {{ Str::plural('item', $lineCount) }}

                <flux:button :href="route('collections.index')" wire:navigate variant="ghost" icon="arrow-left">
                    Continue shopping
                </flux:button>

            @if ($lines->isEmpty())

                    <flux:icon name="shopping-bag" class="mx-auto size-12 text-zinc-400 dark:text-zinc-600" />

Your cart is empty

                    <flux:button :href="route('collections.index')" wire:navigate variant="primary" class="mt-6">
                        Browse products
                    </flux:button>

            @else

                    @foreach ($lines as $line)

getKey() }}">
                            variant->product->handle) }}" wire:navigate class="flex aspect-square items-center justify-center rounded-md border border-zinc-200 bg-zinc-100 text-zinc-400 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-600">
                                <flux:icon name="shopping-bag" class="size-7" />

                                variant->product->handle) }}" wire:navigate class="font-medium text-zinc-950 hover:underline dark:text-white">
                                    {{ $line->variant->product->title }}

                                    {{ $line->variant->optionValues->map(fn ($value) => $value->option->name.': '.$value->value)->implode(' / ') ?: ($line->variant->sku ?: 'Default') }}

                                <x-storefront.price :amount="$line->unit_price_amount" :currency="$cart->currency" class="text-sm" />

                                    <button type="button" wire:click="decreaseQuantity({{ $line->getKey() }})" class="flex size-10 items-center justify-center border-r border-zinc-200 text-sm dark:border-zinc-700" aria-label="Decrease {{ $line->variant->product->title }} quantity">-</button>
                                    {{ $line->quantity }}
                                    <button type="button" wire:click="increaseQuantity({{ $line->getKey() }})" class="flex size-10 items-center justify-center border-l border-zinc-200 text-sm dark:border-zinc-700" aria-label="Increase {{ $line->variant->product->title }} quantity">+</button>

                                    <x-storefront.price :amount="$line->line_total_amount" :currency="$cart->currency" class="justify-end" />
                                    <flux:button wire:click="removeLine({{ $line->getKey() }})" variant="ghost" size="sm" icon="trash" class="mt-2" aria-label="Remove {{ $line->variant->product->title }}" />

                    @endforeach

            @endif

Summary

                    Subtotal
                    @if (…943 chars truncated…

                    Shipping
                    @if (! $cart || $lineCount === 0)
                        -
                    @elseif (! $requiresShipping || $discountFreeShipping)
                        Free
                    @elseif ($estimatedShipping !== null)
                        <x-storefront.price :amount="$estimatedShipping" :currency="$cart->currency" />
                    @else
                        Unavailable
                    @endif

                    Estimated total
                    @if ($cart)
                        <x-storefront.price :amount="$estimatedTotal" :currency="$cart->currency" />
                    @else
                        -
                    @endif

            @if ($cart && $lineCount > 0)
                <form wire:submit="applyDiscount" class="mt-5 border-t border-zinc-200 pt-5 dark:border-zinc-800">

                            <flux:input wire:model="discountCode" label="Discount code" placeholder="WELCOME10" />

                        <flux:button type="submit" variant="ghost" icon="tag" class="shrink-0">
                            Apply
                        </flux:button>

                    <flux:error name="discountCode" />

                    @if ($appliedDiscountCode)

                            <flux:badge color="green">{{ $appliedDiscountCode }}</flux:badge>
                            <flux:button type="button" wire:click="removeDiscount" variant="ghost" size="sm" icon="x-mark">
                                Remove
                            </flux:button>

                    @endif
                </form>

                <form wire:submit="estimateShipping" class="mt-5 border-t border-zinc-200 pt-5 dark:border-zinc-800">

                        <flux:select wire:model.live="shippingCountry" label="Ship to">
                            <flux:select.option value="DE">Germany</flux:select.option>
                            <flux:select.option value="AT">Austria</flux:select.option>
                            <flux:select.option value="CH">Switzerland</flux:select.option>
                            <flux:select.option value="US">United States</flux:select.option>
                        </flux:select>

                            <flux:input wire:model.live.debounce.400ms="shippingPostalCode" label="Postal code" placeholder="10115" />
                            <flux:input wire:model.live.debounce.400ms="shippingProvinceCode" label="Region code" placeholder="BE" />

                    <flux:error name="shippingCountry" />

                    <flux:button type="submit" variant="ghost" icon="truck" class="mt-4 w-full">
                        Estimate shipping
                    </flux:button>

                        @forelse ($rates as $rate)

getKey() }}">
                                {{ $rate->name }}
                                <x-storefront.price :amount="data_get($rateAmounts, $rate->getKey(), 0)" :currency="$cart->currency" class="justify-end text-sm" />

                        @empty

                                {{ $requiresShipping ? 'No rates are available.' : 'No shipping needed.' }}

                        @endforelse

                </form>
            @endif

            <flux:button wire:click="checkout" variant="primary" class="mt-6 w-full" :disabled="$lineCount === 0">
                Checkout
            </flux:button>


command: sed -n '1,340p' app/Services/CartService.php

aggregated_output:
<?php

namespace App\Services;

use App\Enums\CartStatus;
use App\Enums\ProductStatus;
use App\Enums\VariantStatus;
use App\Exceptions\CartVersionMismatchException;
use App\Exceptions\InvalidCartOperationException;
use App\Models\Cart;
use App\Models\CartLine;
use App\Models\Customer;
use App\Models\InventoryItem;
use App\Models\ProductVariant;
use App\Models\Store;
use Illuminate\Support\Facades\DB;

class CartService
{
    public function __construct(
        private readonly InventoryService $inventory,
    ) {}

    public function create(Store $store, ?Customer $customer = null): Cart
    {
        return Cart::withoutGlobalScopes()->create([
            'store_id' => $store->getKey(),
            'customer_id' => $customer?->getKey(),
            'currency' => $store->default_currency,
            'cart_version' => 1,
            'status' => CartStatus::Active,
        ]);
    }

    public function getOrCreateForSession(Store $store, ?Customer $customer = null): Cart
    {
        $sessionCartId = session('cart_id');

        if ($customer instanceof Customer) {
            $customerCart = Cart::withoutGlobalScopes()
                ->where('store_id', $store->getKey())
                ->where('customer_id', $customer->getKey())
                ->where('status', CartStatus::Active)
                ->latest('id')
                ->first() ?? $this->create($store, $customer);

            if ($sessionCartId) {
                $guestCart = Cart::withoutGlobalScopes()
                    ->where('store_id', $store->getKey())
                    ->whereNull('customer_id')
                    ->where('status', CartStatus::Active)
                    ->find($sessionCartId);

                if ($guestCart instanceof Cart && $guestCart->isNot($customerCart)) {
                    $customerCart = $this->mergeOnLogin($guestCart, $customerCart);
                }

                session()->forget('cart_id');
            }

            return $customerCart->refresh();
        }

        if ($sessionCartId) {
            $cart = Cart::withoutGlobalScopes()
                ->where('store_id', $store->getKey())
                ->whereNull('customer_id')
                ->where('status', CartStatus::Active)
                ->find($sessionCartId);

            if ($cart instanceof Cart) {
                return $cart;
            }
        }

        $cart = $this->create($store);
        session(['cart_id' => $cart->getKey()]);

        return $cart;
    }

    public function currentForSession(Store $store, ?Customer $customer = null): ?Cart
    {
        if ($customer instanceof Customer) {
            $customerCart = Cart::withoutGlobalScopes()
                ->where('store_id', $store->getKey())
                ->where('customer_id', $customer->getKey())
                ->where('status', CartStatus::Active)
                ->latest('id')
                ->first();

            if ($customerCart instanceof Cart) {
                return $customerCart;
            }
        }

        $sessionCartId = session('cart_id');

        if (! $sessionCartId) {
            return null;
        }

        return Cart::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->where('status', CartStatus::Active)
            ->where(function ($query) use ($customer): void {
                if ($customer instanceof Customer) {
                    $query
                        ->whereNull('customer_id')
                        ->orWhere('customer_id', $customer->getKey());

                    return;
                }

                $query->whereNull('customer_id');
            })
            ->find($sessionCartId);
    }

    public function addLine(Cart $cart, int $variantId, int $quantity, ?int $expectedVersion = null): CartLine
    {
        $this->assertPositiveQuantity($quantity);

        return DB::transaction(function () use ($cart, $variantId, $quantity, $expectedVersion): CartLine {
            $lockedCart = $this->freshCart($cart);
            $this->assertExpectedVersion($lockedCart, $expectedVersion);
            $this->assertCartIsActive($lockedCart);

            $variant = $this->purchasableVariant($lockedCart, $variantId);
            $line = CartLine::withoutGlobalScopes()
                ->where('cart_id', $lockedCart->getKey())
                ->where('variant_id', $variant->getKey())
                ->first();
            $newQuantity = ($line?->quantity ?? 0) + $quantity;

            $this->assertAvailable($variant->inventoryItem, $newQuantity);

            if (! $line instanceof CartLine) {
                $line = new CartLine([
                    'cart_id' => $lockedCart->getKey(),
                    'variant_id' => $variant->getKey(),
                    'unit_price_amount' => $variant->price_amount,
                ]);
            }

            $this->fillLineAmounts($line, $newQuantity, $line->unit_price_amount ?: $variant->price_amount);
            $line->save…1104 chars truncated…dCart);

            return $line->refresh();
        });
    }

    public function removeLine(Cart $cart, int $lineId, ?int $expectedVersion = null): void
    {
        DB::transaction(function () use ($cart, $lineId, $expectedVersion): void {
            $lockedCart = $this->freshCart($cart);
            $this->assertExpectedVersion($lockedCart, $expectedVersion);
            $this->assertCartIsActive($lockedCart);

            CartLine::withoutGlobalScopes()
                ->where('cart_id', $lockedCart->getKey())
                ->whereKey($lineId)
                ->delete();

            $this->incrementVersion($lockedCart);
        });
    }

    public function mergeOnLogin(Cart $guest, Cart $customer): Cart
    {
        return DB::transaction(function () use ($guest, $customer): Cart {
            $guestCart = $this->freshCart($guest);
            $customerCart = $this->freshCart($customer);

            CartLine::withoutGlobalScopes()
                ->where('cart_id', $guestCart->getKey())
                ->get()
                ->each(function (CartLine $guestLine) use ($customerCart): void {
                    $existingLine = CartLine::withoutGlobalScopes()
                        ->where('cart_id', $customerCart->getKey())
                        ->where('variant_id', $guestLine->variant_id)
                        ->first();

                    if ($existingLine instanceof CartLine) {
                        $quantity = max($existingLine->quantity, $guestLine->quantity);
                        $this->fillLineAmounts($existingLine, $quantity, $existingLine->unit_price_amount);
                        $existingLine->save();
                        $guestLine->delete();

                        return;
                    }

                    $guestLine->forceFill(['cart_id' => $customerCart->getKey()])->save();
                });

            $guestCart->forceFill(['status' => CartStatus::Abandoned])->save();
            $this->incrementVersion($customerCart);

            return $customerCart->refresh();
        });
    }

    private function freshCart(Cart $cart): Cart
    {
        return Cart::withoutGlobalScopes()
            ->whereKey($cart->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function purchasableVariant(Cart $cart, int $variantId): ProductVariant
    {
        $variant = ProductVariant::withoutGlobalScopes()
            ->with([
                'product' => fn ($query) => $query->withoutGlobalScopes(),
                'inventoryItem' => fn ($query) => $query->withoutGlobalScopes(),
            ])
            ->findOrFail($variantId);

        if ((int) $variant->product->store_id !== (int) $cart->store_id) {
            throw InvalidCartOperationException::because('Variant does not belong to this store.');
        }

        if ($variant->product->status !== ProductStatus::Active || $variant->product->published_at === null) {
            throw InvalidCartOperationException::because('Product is not active.');
        }

        if ($variant->status !== VariantStatus::Active) {
            throw InvalidCartOperationException::because('Variant is not active.');
        }

        if (! $variant->inventoryItem instanceof InventoryItem) {
            throw InvalidCartOperationException::because('Variant inventory is missing.');
        }

        return $variant;
    }

    private function assertAvailable(InventoryItem $item, int $quantity): void
    {
        if (! $this->inventory->checkAvailability($item, $quantity)) {
            throw \App\Exceptions\InsufficientInventoryException::forQuantity($item->availableQuantity(), $quantity);
        }
    }

    private function fillLineAmounts(CartLine $line, int $quantity, int $unitPrice): void
    {
        $subtotal = $unitPrice * $quantity;

        $line->forceFill([
            'quantity' => $quantity,
            'unit_price_amount' => $unitPrice,
            'line_subtotal_amount' => $subtotal,
            'line_discount_amount' => 0,
            'line_total_amount' => $subtotal,
        ]);
    }

    private function incrementVersion(Cart $cart): void
    {
        $cart->forceFill([
            'cart_version' => $cart->cart_version + 1,
        ])->save();
    }

    private function assertExpectedVersion(Cart $cart, ?int $expectedVersion): void
    {
        if ($expectedVersion !== null && $expectedVersion !== $cart->cart_version) {
            throw new CartVersionMismatchException($expectedVersion, $cart->cart_version);
        }
    }

    private function assertCartIsActive(Cart $cart): void
    {
        if ($cart->status !== CartStatus::Active) {
            throw InvalidCartOperationException::because('Cart is not active.');
        }
    }

    private function assertPositiveQuantity(int $quantity): void
    {
        if ($quantity <= 0) {
            throw InvalidCartOperationException::because('Cart line quantity must be greater than zero.');
        }
    }
}


output:
Chunk ID: 3f2f2b
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1369
Output:
<?php

namespace App\Livewire\Storefront\Products;

use App\Enums\InventoryPolicy;
use App\Models\Customer;
use App\Models\Product;
use App\Models\ProductOptionValue;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Services\CartService;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;

class Show extends Component
{
    public string $handle;

    public int $storeId;

    /**
     * @var array<string, string>
     */
    public array $selectedOptions = [];

    public int $quantity = 1;

    public function mount(string $handle): void
    {
        $this->handle = $handle;
        $this->storeId = $this->store()->getKey();

        $variant = $this->product()->variants->firstWhere('is_default', true)
            ?? $this->product()->variants->first();

        if ($variant instanceof ProductVariant) {
            $this->selectedOptions = $variant->optionValues
                ->mapWithKeys(fn (ProductOptionValue $value): array => [$value->option->name => $value->value])
                ->all();
        }
    }

    public function selectOption(string $optionName, string $value): void
    {
        $this->selectedOptions[$optionName] = $value;
        $this->quantity = 1;
    }

    public function increaseQuantity(): void
    {
        $variant = $this->selectedVariant();
        $max = $variant?->inventoryItem?->policy === InventoryPolicy::Deny
            ? max(1, $variant->inventoryItem->availableQuantity())
            : null;

        if ($max === null || $this->quantity < $max) {
            $this->quantity++;
        }
    }

    public function decreaseQuantity(): void
    {
        $this->quantity = max(1, $this->quantity - 1);
    }

    public function addToCart(): void
    {
        $store = $this->store();
        $variant = $this->selectedVariant();

        if (! $variant instanceof ProductVariant || ! $this->canAddToCart()) {
            return;
        }

        $customer = Auth::guard('customer')->user();
        $customer = $customer instanceof Customer ? $customer : null;

        app(CartService::class)->addLine(
            app(CartService::class)->getOrCreateForSession($store, $customer),
            $variant->getKey(),
            $this->quantity,
        );

        $this->dispatch('cart-updated');
        $this->dispatch('toast', type: 'success', message: __('Added to cart'));
    }

    public function store(): Store
    {
        if (isset($this->storeId)) {
            $store = Store::query()->findOrFail($this->storeId);
            app()->instance('current_store', $store);

            return $store;
        }

        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        return $store;
    }

    public function product(): Product
    {
        $this->store();

        return Product::query()
            ->with(['options.values', 'variants.inventoryItem', 'variants.optionValues.option', 'collections'])
            ->where('handle', $this->handle)
            ->where('status', 'active')
            ->whereNotNull('published_at')
            ->firstOrFail();
    }

    public function selectedVariant(): ?ProductVariant
    {
        $product = $this->product();

        if ($product->options->isEmpty()) {
            return $product->variants->first();
        }

        return $product->variants->first(function (ProductVariant $variant): bool {
            $options = $variant->optionValues
                ->mapWithKeys(fn (ProductOptionValue $value): array => [$value->option->name => $value->value])
                ->all();

            return $options === $this->selectedOptions;
        });
    }

    public function canAddToCart(): bool
    {
        $variant = $this->selectedVariant();

        if (! $variant instanceof ProductVariant || ! $variant->isPurchasable()) {
            return false;
        }

        $inventory = $variant->inventoryItem;

        return $inventory?->policy === InventoryPolicy::Continue
            || ($inventory?->availableQuantity() ?? 0) >= $this->quantity;
    }

    /**
     * @return array{message: string, class: string}
     */
    public function stockState(): array
    {
        $variant = $this->selectedVariant();
        $inventory = $variant?->inventoryItem;

        if (! $inventory) {
            return ['message' => 'Unavailable', 'class' => 'text-red-700 dark:text-red-300'];
        }

        if ($inventory->policy === InventoryPolicy::Continue && $inventory->availableQuantity() <= 0) {
            return ['message' => 'Available on backorder', 'class' => 'text-blue-700 dark:text-blue-300'];
        }

        if ($inventory->availableQuantity() <= 0) {
            return ['message' => 'Out of stock', 'class' => 'text-red-700 dark:text-red-300'];
        }

        if ($inventory->availableQuantity() <= 10) {
            return ['message' => "Only {$inventory->availableQuantity()} left in stock", 'class' => 'text-amber-700 dark:text-amber-300'];
        }

        return ['message' => 'In stock', 'class' => 'text-green-700 dark:text-green-300'];
    }

    public function render(): mixed
    {
        $product = $this->product();

        return view('livewire.storefront.products.show', [
            'product' => $product,
            'selectedVariant' => $this->selectedVariant(),
            'stockState' => $this->stockState(),
        ])->layout('layouts.storefront', [
            'title' => $product->title,
        ]);
    }
}


output:
Chunk ID: d23d45
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1586
Output:

    <x-storefront.breadcrumbs :items="[
        ['label' => $product->collections->first()?->title ?? 'Products', 'url' => $product->collections->first() ? route('collections.show', $product->collections->first()->handle) : route('collections.index')],
        ['label' => $product->title],
    ]" />

                <flux:icon name="shopping-bag" class="size-20" />

                    @if ($selectedVariant?->compare_at_amount && $selectedVariant->compare_at_amount > $selectedVariant->price_amount)
                        Sale
                    @endif
                    @foreach ($product->tags ?? [] as $tag)
                        {{ $tag }}
                    @endforeach

{{ $product->title }}

                @if ($selectedVariant)
                    <x-storefront.price :amount="$selectedVariant->price_amount" :compare-at="$selectedVariant->compare_at_amount" :currency="$selectedVariant->currency" class="text-2xl" aria-live="polite" />
                @endif

            @if ($product->options->isNotEmpty())

                    @foreach ($product->options as $option)
                        <fieldset class="space-y-3" wire:key="product-option-selector-{{ $option->getKey() }}">
                            <legend class="text-sm font-medium text-zinc-950 dark:text-white">{{ $option->name }}</legend>

                                @foreach ($option->values as $value)
                                    @php($selected = ($selectedOptions[$option->name] ?? null) === $value->value)
                                    <button
                                        type="button"
                                        wire:click="selectOption(@js($option->name), @js($value->value))"
                                        @class([
                                            'min-h-10 rounded-md border px-4 py-2 text-sm font-medium transition',
                                            'border-blue-700 bg-blue-50 text-blue-800 dark:border-blue-300 dark:bg-blue-950 dark:text-blue-100' => $selected,
                                            'border-zinc-200 text-zinc-700 hover:border-zinc-400 dark:border-zinc-700 dark:text-zinc-200 dark:hover:border-zinc-500' => ! $selected,
                                        ])
                                        aria-pressed="{{ $selected ? 'true' : 'false' }}"
                                    >
                                        {{ $value->value }}
                                    </button>
                                @endforeach

                        </fieldset>
                    @endforeach

            @endif

{{ $stockState['message'] }}

                    <button type="button" wire:click="decreaseQuantity" class="flex size-11 items-center justify-center border-r border-zinc-200 text-lg dark:border-zinc-700" aria-label="Decrease quantity">-</button>
                    <input wire:model.live="quantity" type="number" min="1" class="h-11 w-full border-0 bg-transparent text-center text-sm" aria-label="Quantity">
                    <button type="button" wire:click="increaseQuantity" class="flex size-11 items-center justify-center border-l border-zinc-200 text-lg dark:border-zinc-700" aria-label="Increase quantity">+</button>

                <flux:button wire:click="addToCart" variant="primary" class="w-full" :disabled="! $this->canAddToCart()">
                    {{ $this->canAddToCart() ? 'Add to cart' : 'Sold out' }}
                </flux:button>

            @if ($product->description_html)

                    {!! $product->description_html !!}

            @endif

Vendor

{{ $product->vendor ?: '-' }}

Product type

{{ $product->product_type ?: '-' }}

                @if ($selectedVariant)

SKU

{{ $selectedVariant->sku ?: '-' }}

Shipping

{{ $selectedVariant->requires_shipping ? 'Required' : 'Digital delivery' }}

                @endif