has('user_id')) { return redirect($router->route('show-register-form')); } secure(); $parameters = $router->current()->parameters(); $item = Item::find((int) $parameters['item']); if (!$item) { return redirect($router->route('show-items')); } $data = validate($_POST, [ 'location_id' => ['required'], 'quantity' => ['required', 'positive_integer'], 'notes' => [], ], 'withdraw_errors'); $location = Location::find((int) $data['location_id']); if (!$location) { return redirect($router->route('show-withdraw-stock-form', ['item' => $item->id])); } $stock = Stock::forItemAtLocation($item->id, $location->id); $quantity = (int) $data['quantity']; if ($quantity > $stock->quantity) { session()->put('withdraw_errors', [ 'quantity' => ['Not enough stock at this location to withdraw that much'], ]); return redirect($router->route('show-withdraw-stock-form', ['item' => $item->id])); } $stock->quantity = $stock->quantity - $quantity; $stock->save(); $movement = new StockMovement(); $movement->item_id = $item->id; $movement->location_id = $location->id; $movement->type = 'withdraw'; $movement->quantity_change = -$quantity; $movement->quantity_after = $stock->quantity; $movement->notes = $data['notes'] ?? ''; $movement->user_id = session('user_id'); $movement->save(); $this->alertIfLowStock($item); return redirect($router->route('view-item', ['item' => $item->id])); } private function alertIfLowStock(Item $item): void { if ($item->reorder_level <= 0) { return; } $total = array_sum(array_map( fn($row) => $row->quantity, Stock::where('item_id', $item->id)->all(), )); if ($total > $item->reorder_level) { return; } app('queue')->push(function ($itemName, $total, $reorderLevel) { app('email') ->to(config('warehouse.alert_email')) ->subject("Low stock: {$itemName}") ->text("{$itemName} is at {$total} units, at or below its reorder level of {$reorderLevel}.") ->send(); }, $item->name, $total, $item->reorder_level); } }