88 lines
4.2 KiB
PHP
88 lines
4.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Enums\PurchasingRole;
|
|
use App\Models\StockItem;
|
|
use App\Models\StockMovement;
|
|
use App\Models\Warehouse;
|
|
use App\Services\RequisitionWorkflow;
|
|
use Brick\Math\BigDecimal;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\Rule;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
class StockController extends Controller
|
|
{
|
|
private function access(Request $request, bool $manage = false): void
|
|
{
|
|
$roles = $manage ? [PurchasingRole::Admin, PurchasingRole::Warehouse] : [PurchasingRole::Admin, PurchasingRole::Warehouse, PurchasingRole::Procurement, PurchasingRole::Finance];
|
|
abort_unless($request->user()->hasFunctions($roles), 403);
|
|
}
|
|
|
|
public function index(Request $request): Response
|
|
{
|
|
$this->access($request);
|
|
$filters = $request->validate([
|
|
'search' => 'nullable|string|max:100',
|
|
'warehouse_id' => ['nullable', 'integer', Rule::exists('warehouses', 'id')->where('tenant_id', $request->user()->tenant_id)],
|
|
]);
|
|
$items = StockItem::query()->orderBy('code')->get(['id', 'code', 'name', 'unit']);
|
|
$warehouses = Warehouse::query()->orderBy('code')->get(['id', 'code', 'name']);
|
|
$selected = StockItem::query();
|
|
if (! empty($filters['search'])) {
|
|
$selected->where(fn ($q) => $q->where('code', 'like', '%'.$filters['search'].'%')->orWhere('name', 'like', '%'.$filters['search'].'%'));
|
|
}
|
|
$movements = StockMovement::query()->whereIn('stock_item_id', $selected->select('id'));
|
|
if (! empty($filters['warehouse_id'])) {
|
|
$movements->where('warehouse_id', $filters['warehouse_id']);
|
|
}
|
|
$balances = (clone $movements)->selectRaw('stock_item_id, warehouse_id, SUM(quantity_milli) as quantity_milli')->groupBy('stock_item_id', 'warehouse_id')->get()->map(fn ($balance) => [
|
|
'stock_item_id' => $balance->stock_item_id, 'warehouse_id' => $balance->warehouse_id,
|
|
'quantity_milli' => BigDecimal::of($balance->quantity_milli)->toInt(),
|
|
]);
|
|
|
|
return Inertia::render('stock/index', [
|
|
'items' => $items, 'warehouses' => $warehouses, 'balances' => $balances,
|
|
'movements' => $movements->latest('id')->paginate(20)->withQueryString(), 'filters' => $filters,
|
|
'canManage' => $request->user()->hasFunctions([PurchasingRole::Admin, PurchasingRole::Warehouse]),
|
|
]);
|
|
}
|
|
|
|
public function item(Request $request, RequisitionWorkflow $audit): RedirectResponse
|
|
{
|
|
$this->access($request, true);
|
|
$request->merge(['code' => Str::upper(trim($request->string('code')->toString())), 'unit' => Str::lower(trim($request->string('unit')->toString()))]);
|
|
$data = $request->validate([
|
|
'code' => ['required', 'regex:/^[A-Z0-9][A-Z0-9._-]{0,29}$/', Rule::unique('stock_items')->where('tenant_id', $request->user()->tenant_id)],
|
|
'name' => 'required|string|max:200', 'unit' => 'required|string|max:30',
|
|
]);
|
|
DB::transaction(function () use ($request, $audit, $data) {
|
|
$item = StockItem::query()->create([...$data, 'tenant_id' => $request->user()->tenant_id, 'created_by' => $request->user()->id]);
|
|
$audit->audit($request->user(), 'stock.item_created', null, null, $item->toArray());
|
|
});
|
|
|
|
return back();
|
|
}
|
|
|
|
public function warehouse(Request $request, RequisitionWorkflow $audit): RedirectResponse
|
|
{
|
|
$this->access($request, true);
|
|
$request->merge(['code' => Str::upper(trim($request->string('code')->toString()))]);
|
|
$data = $request->validate([
|
|
'code' => ['required', 'regex:/^[A-Z0-9][A-Z0-9._-]{0,29}$/', Rule::unique('warehouses')->where('tenant_id', $request->user()->tenant_id)],
|
|
'name' => 'required|string|max:200',
|
|
]);
|
|
DB::transaction(function () use ($request, $audit, $data) {
|
|
$warehouse = Warehouse::query()->create([...$data, 'tenant_id' => $request->user()->tenant_id, 'created_by' => $request->user()->id]);
|
|
$audit->audit($request->user(), 'stock.warehouse_created', null, null, $warehouse->toArray());
|
|
});
|
|
|
|
return back();
|
|
}
|
|
}
|