81 lines
4.5 KiB
PHP
81 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\GoodsReceipt;
|
|
use App\Models\SupplyRecord;
|
|
use App\Models\User;
|
|
use App\Services\InventoryCorrectionPage;
|
|
use App\Services\InventoryDispositions;
|
|
use App\Services\InventoryReversals;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Inertia\Inertia;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class InventoryReversalController extends Controller
|
|
{
|
|
public function index(Request $request, InventoryReversals $workflow): Response
|
|
{
|
|
$actor = $request->user('web');
|
|
abort_unless($actor instanceof User, 403);
|
|
$capabilities = [];
|
|
foreach (['read', 'prepare', 'review', 'execute'] as $capability) {
|
|
$capabilities[$capability] = $workflow->allows($actor, $capability);
|
|
}
|
|
abort_unless(collect($capabilities)->contains(fn (bool $allow) => $allow), 403);
|
|
|
|
return DB::transaction(function () use ($request, $workflow, $actor, $capabilities) {
|
|
if (DB::getDriverName() === 'pgsql' && DB::transactionLevel() === 1) {
|
|
DB::statement('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY');
|
|
}
|
|
|
|
return $this->page($request, $workflow, $actor, $capabilities);
|
|
});
|
|
}
|
|
|
|
/** @param array<string,bool> $capabilities */
|
|
private function page(Request $request, InventoryReversals $workflow, User $actor, array $capabilities): Response
|
|
{
|
|
$page = app(InventoryCorrectionPage::class)->read($request, $actor, 'stock_reversal');
|
|
['ready' => $ready, 'focus' => $focus, 'records' => $records] = $page;
|
|
$operations = [];
|
|
$receipts = [];
|
|
if ($ready && $capabilities['prepare']) {
|
|
$operations = app(InventoryCorrectionPage::class)->operations($records->pluck('data.source_operation_id')->push($page['lookup']['operation']), $page['lookup']['search'])
|
|
->map(fn ($op) => ['id' => $op->id, 'label' => $op->reference.' · '.$op->snapshot['stock_item']['name'].' · '.$op->snapshot['warehouse']['name']])->values()->all();
|
|
foreach (app(InventoryCorrectionPage::class)->receipts($records->pluck('data.receipt_item_id')->push($page['lookup']['receipt']), $page['lookup']['search']) as $line) {
|
|
$receipt = GoodsReceipt::query()->whereKey($line->goods_receipt_id)->firstOrFail();
|
|
$receipts[] = ['id' => $line->id, 'label' => $receipt->number.' · '.$line->snapshot['stock_item']['name'].' · '.$line->snapshot['warehouse']['name']];
|
|
}
|
|
}
|
|
$other = app(InventoryDispositions::class);
|
|
|
|
Inertia::encryptHistory();
|
|
$response = Inertia::render('stock/reversals', ['ready' => $ready, 'actorId' => $actor->id, 'today' => today()->toDateString(), 'capabilities' => $capabilities,
|
|
'recordPagination' => $page['pagination'], 'filters' => $page['filters'],
|
|
'sourceSearch' => $page['lookup']['search'], 'sourceFormKey' => $page['lookup']['form'],
|
|
'focusRecordId' => $focus->id ?? null, 'focusChanged' => $focus !== null && $records->first()?->id !== $focus->id,
|
|
'canViewDispositions' => collect(['read', 'prepare', 'review', 'execute'])->contains(fn ($a) => $other->allows($actor, $a)),
|
|
'records' => $records->map(fn (SupplyRecord $record) => [...$record->toArray(), 'canApprove' => $workflow->canAct($actor, $record, 'approve'),
|
|
'canReturn' => $workflow->canAct($actor, $record, 'return'), 'canExecute' => $workflow->canAct($actor, $record, 'execute'),
|
|
'executionSourceCurrent' => $record->state === 'approved' ? $workflow->executionSourceCurrent($record) : null]), 'operations' => $operations, 'receipts' => $receipts,
|
|
'history' => $ready ? SupplyRecord::query()->where('kind', 'stock_reversal')->whereIn('record_key', $records->pluck('record_key'))->latest('id')->get()->groupBy('record_key') : []])->toResponse($request);
|
|
$response->headers->set('Cache-Control', 'private, no-store, max-age=0');
|
|
|
|
return $response;
|
|
}
|
|
|
|
public function save(Request $request, InventoryReversals $workflow): RedirectResponse
|
|
{
|
|
$actor = $request->user('web');
|
|
abort_unless($actor instanceof User, 403);
|
|
abort_unless(Schema::hasTable('supply_records'), 503, 'Instalação do diário pendente.');
|
|
$workflow->save($actor, $request->all());
|
|
|
|
return back()->with('success', 'Estorno registado com a origem preservada.');
|
|
}
|
|
}
|