80 lines
3.2 KiB
PHP
80 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\StockMovement;
|
|
use App\Models\StockVariant;
|
|
use App\Models\UniformItem;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\Rule;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class InventoryController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
return view('inventory.index', [
|
|
'items' => 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'];
|
|
}
|
|
}
|