# Recovery Script — Order C1371 (Stock Not Deducted)

Run on the **live server** via `php artisan tinker` after deploying the 2026-06-24 fixes.

## What this does

- Clears `stock_deducted_at` so the idempotency guard won't block the run
- Calls `processOrderDeductions()` to deduct qty from Somerset4x4 stock, clear the reservation, and create the IN/OUT Move record
- Dispatches `SyncProductToChannels` to push the updated stock level to Shopify

## Script

```php
$order = \Webkul\ChannelOrders\Models\Order::find(372); // C1371
echo "Order: {$order->name}, Status: {$order->status->value}, Deducted: {$order->stock_deducted_at}\n";

// Inspect lines to confirm product_id is set
foreach ($order->orderLines as $line) {
    echo "  Line: sku={$line->sku}, product_id={$line->product_id}, qty={$line->quantity}\n";
}

// Confirm stock before running
$pq = \Webkul\Inventory\Models\ProductQuantity::where('product_id', 1176)
    ->whereHas('location', fn($q) => $q->where('warehouse_id', 2)->where('type','internal'))
    ->first();
echo "Before: qty={$pq?->quantity}, reserved={$pq?->reserved_quantity}\n";

// Reset guard so it will run (in case a partial deploy already set it)
\Webkul\ChannelOrders\Models\Order::withoutEvents(
    fn () => $order->forceFill(['stock_deducted_at' => null])->save()
);

// Run deductions
$observer = new \Webkul\ChannelOrders\Models\Observers\OrderObserver();
$observer->processOrderDeductions($order->fresh());
$observer->dispatchChannelSync($order);

// Confirm stock after
$pq->refresh();
echo "After: qty={$pq->quantity}, reserved={$pq->reserved_quantity}\n";
echo "stock_deducted_at: {$order->fresh()->stock_deducted_at}\n";
echo "Done. Check the queue and IN/OUT tab for product 1176.\n";
```

## Expected output

```
Before: qty=1, reserved=1
After:  qty=0, reserved=0
stock_deducted_at: 2026-06-24 ...
```

The Somerset4x4 stock will drop from 1→0, the reservation will clear,
a Move record will appear in the IN/OUT tab, and a SyncProductToChannels
job will be dispatched to update the Shopify `in_stock` metafield to false.
