commit14
This commit is contained in:
@@ -8,41 +8,66 @@ use App\Models\StockItem;
|
||||
use App\Models\User;
|
||||
use App\Models\Warehouse;
|
||||
use App\Models\WarehouseRequest;
|
||||
use App\Services\InternalSupplyTrace;
|
||||
use App\Services\OrganizationAccess;
|
||||
use App\Services\WarehouseFulfilment;
|
||||
use App\Services\WarehouseRequests;
|
||||
use App\Services\WarehouseWorkdesk;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Inertia\Inertia;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class WarehouseRequestController extends Controller
|
||||
{
|
||||
public function index(Request $request): Response
|
||||
public function index(Request $request, WarehouseWorkdesk $desk): Response
|
||||
{
|
||||
$actor = $request->user('web');
|
||||
abort_unless($actor instanceof User && $actor->hasFunctions(['admin', 'warehouse_request_read', 'warehouse_request_prepare', 'warehouse_request_review', 'warehouse_request_deliver']), 403);
|
||||
$prepare = $actor->hasFunctions(['warehouse_request_prepare']) && ! app(OrganizationAccess::class)->maintenanceOnly($actor);
|
||||
$ready = Schema::hasTable('warehouse_requests');
|
||||
$query = WarehouseRequest::query();
|
||||
if (! $actor->hasFunctions(['admin', 'warehouse_request_read']) && ! ($actor->hasFunctions(['warehouse_request_deliver']) && $actor->hasFunctions(['warehouse']))) {
|
||||
$query->where(function ($q) use ($actor) {
|
||||
$q->where('created_by', $actor->id);
|
||||
if ($actor->hasFunctions(['warehouse_request_review']) && $actor->department_id !== null) {
|
||||
$q->orWhere('snapshot->requester->department_id', $actor->department_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
Inertia::encryptHistory();
|
||||
$response = Inertia::render('stock/requests', ['ready' => $ready, 'canPrepare' => $prepare, 'fulfilmentReady' => Schema::hasTable('warehouse_request_events'),
|
||||
'records' => $ready ? $query->latest('id')->paginate(15, ['id', 'status', 'snapshot', 'created_at'])->withQueryString()->through(fn ($r) => ['id' => $r->id, 'status' => $r->status, 'snapshot' => $r->snapshot, 'progress' => app(WarehouseFulfilment::class)->progress($r)]) : null,
|
||||
'warehouses' => $prepare ? Warehouse::query()->orderBy('code')->get(['id', 'code', 'name']) : [],
|
||||
'items' => $prepare ? StockItem::query()->orderBy('code')->get(['id', 'code', 'name', 'unit']) : [],
|
||||
'costCenters' => $prepare ? CostCenter::query()->where('department_id', $actor->department_id)->orderBy('code')->get(['id', 'code', 'name']) : [],
|
||||
'equipment' => $prepare ? Equipment::query()->where('department_id', $actor->department_id)->orderBy('code')->get(['id', 'code', 'description']) : []])->toResponse($request);
|
||||
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
|
||||
|
||||
return $response;
|
||||
return DB::transaction(function () use ($request, $actor, $desk) {
|
||||
if (DB::getDriverName() === 'pgsql' && DB::transactionLevel() === 1) {
|
||||
DB::statement('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY');
|
||||
}
|
||||
$filters = $request->validate(['view' => 'nullable|in:all,review,reserve,delivery,receipt', 'state' => 'nullable|in:all,draft,submitted,authorized,partial,delivered,closed,rejected,cancelled', 'search' => 'nullable|string|max:100', 'warehouse_id' => ['nullable', 'integer', Rule::exists('warehouses', 'id')->where('tenant_id', $actor->tenant_id)], 'page' => 'nullable|integer|min:1|max:1000000']);
|
||||
$prepare = $actor->hasFunctions(['warehouse_request_prepare']) && ! app(OrganizationAccess::class)->maintenanceOnly($actor);
|
||||
$ready = Schema::hasTable('warehouse_requests');
|
||||
$base = $desk->visible($actor);
|
||||
if (! empty($filters['warehouse_id'])) {
|
||||
$base->where('warehouse_id', $filters['warehouse_id']);
|
||||
}
|
||||
if (! empty($filters['search'])) {
|
||||
$search = trim($filters['search']);
|
||||
if (preg_match('/^(?:RA-)?([1-9][0-9]{0,9})$/iD', $search, $match)) {
|
||||
$base->whereKey($match[1]);
|
||||
} else {
|
||||
$base->where(fn ($q) => $q->whereLike('snapshot->requester->name', '%'.$search.'%')->orWhereLike('snapshot->destination', '%'.$search.'%'));
|
||||
}
|
||||
}
|
||||
$views = $ready ? $desk->views(clone $base, $actor) : [];
|
||||
$query = $desk->forView(clone $base, $actor, $filters['view'] ?? 'all');
|
||||
$states = $ready ? DB::query()->fromSub((clone $query)->selectRaw($desk->stateExpression().' as projected_state')->toBase(), 'request_states')->selectRaw('projected_state, COUNT(*) as total')->groupBy('projected_state')->pluck('total', 'projected_state') : [];
|
||||
if (($filters['state'] ?? 'all') !== 'all') {
|
||||
$query->whereRaw($desk->stateExpression().' = ?', [$filters['state']]);
|
||||
}
|
||||
Inertia::encryptHistory();
|
||||
$response = Inertia::render('stock/requests', ['ready' => $ready, 'canPrepare' => $prepare, 'fulfilmentReady' => Schema::hasTable('warehouse_request_events'),
|
||||
'filters' => ['view' => $filters['view'] ?? 'all', 'state' => $filters['state'] ?? 'all', 'search' => $filters['search'] ?? '', 'warehouse_id' => $filters['warehouse_id'] ?? null], 'views' => $views, 'states' => $states, 'checkedAt' => now()->toIso8601String(),
|
||||
'records' => $ready ? $query->oldest('id')->paginate(15, ['id', 'tenant_id', 'warehouse_id', 'created_by', 'status', 'snapshot', 'created_at'])->withQueryString()->through(function ($r) use ($desk, $actor) {
|
||||
$p = app(WarehouseFulfilment::class)->progress($r);
|
||||
|
||||
return ['id' => $r->id, 'status' => $r->status, 'snapshot' => $r->snapshot, 'progress' => $p, 'health' => $desk->health($r, $p), 'actions' => $desk->actions($actor, $r, $p)];
|
||||
}) : null,
|
||||
'warehouses' => Warehouse::query()->when(! $prepare, fn ($q) => $q->whereIn('id', $ready ? $desk->visible($actor)->select('warehouse_id') : []))->orderBy('code')->get(['id', 'code', 'name']),
|
||||
'items' => $prepare ? StockItem::query()->orderBy('code')->get(['id', 'code', 'name', 'unit']) : [],
|
||||
'costCenters' => $prepare ? CostCenter::query()->where('department_id', $actor->department_id)->orderBy('code')->get(['id', 'code', 'name']) : [],
|
||||
'equipment' => $prepare ? Equipment::query()->where('department_id', $actor->department_id)->orderBy('code')->get(['id', 'code', 'description']) : []])->toResponse($request);
|
||||
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
|
||||
|
||||
return $response;
|
||||
});
|
||||
}
|
||||
|
||||
public function store(Request $request, WarehouseRequests $service): Response
|
||||
@@ -58,22 +83,24 @@ class WarehouseRequestController extends Controller
|
||||
{
|
||||
$actor = $request->user('web');
|
||||
abort_unless($actor instanceof User, 403);
|
||||
$r = WarehouseRequest::query()->findOrFail($id);
|
||||
$owner = $r->created_by === $actor->id && $actor->hasFunctions(['warehouse_request_prepare']);
|
||||
$review = $actor->hasFunctions(['warehouse_request_review']) && $actor->department_id !== null && $actor->department_id === $r->snapshot['requester']['department_id'];
|
||||
$deliver = $actor->hasFunctions(['warehouse_request_deliver']) && $actor->hasFunctions(['warehouse']);
|
||||
abort_unless($owner || $review || $deliver || $actor->hasFunctions(['admin', 'warehouse_request_read']), 403);
|
||||
$p = $service->progress($r);
|
||||
$maintenance = app(OrganizationAccess::class)->maintenanceOnly($actor);
|
||||
Inertia::encryptHistory();
|
||||
$response = Inertia::render('stock/request', ['record' => $r->only(['id', 'snapshot', 'created_at']), 'progress' => $p, 'ready' => Schema::hasTable('warehouse_request_events'),
|
||||
'canSubmit' => ! $maintenance && $owner && $p['state'] === 'draft', 'canReview' => ! $maintenance && $review && ! $owner && $r->created_by !== $actor->id && $p['state'] === 'submitted',
|
||||
'canDeliver' => ! $maintenance && $deliver && $r->created_by !== $actor->id && $p['reviewer_id'] !== $actor->id && in_array($p['state'], ['authorized', 'partial'], true),
|
||||
'canManageReservation' => ! $maintenance && $review && ! $owner && in_array($p['state'], ['authorized', 'partial'], true),
|
||||
'canReceive' => ! $maintenance && $owner])->toResponse($request);
|
||||
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
|
||||
|
||||
return $response;
|
||||
return DB::transaction(function () use ($request, $id, $service, $actor) {
|
||||
if (DB::getDriverName() === 'pgsql' && DB::transactionLevel() === 1) {
|
||||
DB::statement('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY');
|
||||
}
|
||||
$r = WarehouseRequest::query()->findOrFail($id);
|
||||
$desk = app(WarehouseWorkdesk::class);
|
||||
abort_unless($desk->canView($actor, $r), 403);
|
||||
$p = $service->progress($r);
|
||||
Inertia::encryptHistory();
|
||||
$response = Inertia::render('stock/request', ['record' => $r->only(['id', 'snapshot', 'created_at']), 'progress' => $p, 'ready' => Schema::hasTable('warehouse_request_events'),
|
||||
'canViewReturns' => config('stock_returns.enabled') && $actor->hasFunctions(['warehouse_return_read']) && !app(OrganizationAccess::class)->maintenanceOnly($actor),
|
||||
'health' => $desk->health($r, $p), 'people' => $desk->people($r, $p),
|
||||
'supplyTrace' => app(InternalSupplyTrace::class)->forRequest($actor, $r, $p), ...$desk->actions($actor, $r, $p)])->toResponse($request);
|
||||
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
|
||||
|
||||
return $response;
|
||||
});
|
||||
}
|
||||
|
||||
public function command(Request $request, int $id, WarehouseFulfilment $service): Response
|
||||
|
||||
Reference in New Issue
Block a user