UniformItem::with('variants')->orderBy('name')->get(), 'movements' => StockMovement::with('variant.item')->latest()->take(15)->get(), ]); } public function storeItem(Request $request) { $data = $request->validate([ 'code' => ['required', 'string', 'max:40', 'unique:uniform_items'], 'name' => ['required', 'string', 'max:120'], 'description' => ['nullable', 'string', 'max:500'], 'sizes' => ['required', 'array', 'min:1'], 'sizes.*' => ['required', 'string', 'distinct', Rule::in($this->allowedSizes())], 'reorder_level' => ['required', 'integer', 'min:0'], ]); DB::transaction(function () use ($data) { $item = UniformItem::create($data); collect($data['sizes'])->map(fn ($size) => strtoupper(trim($size)))->filter()->unique() ->each(fn ($size) => $item->variants()->create(['size' => $size, 'reorder_level' => $data['reorder_level']])); }); return back()->with('success', 'Uniform and size options added.'); } public function restock(Request $request) { $data = $request->validate([ 'uniform_item_id' => ['required', 'exists:uniform_items,id'], 'stocks' => ['required', 'array', 'min:1'], 'stocks.*' => ['required', 'integer', 'min:1', 'max:100000'], 'notes' => ['nullable', 'string', 'max:500'], ]); $updatedSizes = 0; DB::transaction(function () use ($data, &$updatedSizes) { $variants = StockVariant::whereIn('id', array_keys($data['stocks']))->lockForUpdate()->get()->keyBy('id'); if ($variants->count() !== count($data['stocks']) || $variants->contains(fn ($variant) => $variant->uniform_item_id !== (int) $data['uniform_item_id'])) { throw ValidationException::withMessages(['stocks' => 'One or more selected sizes do not belong to that uniform.']); } foreach ($data['stocks'] as $variantId => $quantity) { $variant = $variants->get((int) $variantId); $variant->increment('quantity', $quantity); StockMovement::create([ 'stock_variant_id' => $variant->id, 'type' => 'restock', 'quantity_change' => $quantity, 'notes' => $data['notes'] ?? null, ]); $updatedSizes++; } }); return back()->with('success', "Stock updated successfully for {$updatedSizes} size(s)."); } private function allowedSizes(): array { return ['XXS', 'XS', 'S', 'M', 'L', 'XL', '2XL', '3XL', '4XL', '26', '28', '30', '32', '34', '36', '38', '40', '42', '44', '46', '48']; } }