Files
2026-11-02 20:27:11 +02:00

59 lines
3.6 KiB
PHP

<?php
namespace Tempo\Purchasing\Delivery;
use App\Modules\Identity\Services\Permissions;
use App\Shared\Context\CompanyContext;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Tempo\Purchasing\SgfCandidate\Port;
final class BudgetSetup
{
public function centre(Request $request)
{
$data = $request->validate(['operation_key' => 'required|uuid', 'code' => ['required', 'string', 'max:100', 'regex:/^[\pL\pN][\pL\pN ._\/-]*$/uD'], 'reason' => 'required|string|min:10|max:500']);
abort_unless(array_diff(array_keys($request->all()), array_keys($data)) === [], 422);
$port = new Port($request->user());
$result = $port->atomic(function () use ($port, $data) {
$port->authorize('configure', null);
$scope = $port->scope();
app(Permissions::class)->require($port->actorId(), $scope['tenant_id'], $scope['company_id'], 'purchasing_budget.create', $scope['unit_id']);
$hash = hash('sha256', json_encode([$data['code'], $data['reason']], JSON_THROW_ON_ERROR));
$receipts = DB::table('cb_ui_commands')->where($scope)->where('actor_id', $port->actorId())->where('command_key', $data['operation_key']);
if ($old = $receipts->first()) {
abort_unless($old->action === 'centre.create' && hash_equals($old->request_hash, $hash), 409);
return json_decode($old->result, true, 16, JSON_THROW_ON_ERROR) + ['replayed' => true];
}
abort_if(DB::table('cb_centres')->where($scope)->where('code', $data['code'])->exists(), 409, 'Centro já cadastrado; seleccione a fonte existente.');
$id = DB::table('cb_centres')->insertGetId($scope + ['code' => $data['code']]);
$result = ['centre_id' => $id, 'code' => $data['code']];
DB::table('cb_audit')->insert($scope + ['actor_id' => $port->actorId(), 'action' => 'centre.created', 'origin_id' => null, 'payload' => json_encode($result + ['reason' => $data['reason']], JSON_THROW_ON_ERROR), 'created_at' => now()]);
DB::table('cb_ui_commands')->insert($scope + ['actor_id' => $port->actorId(), 'command_key' => $data['operation_key'], 'action' => 'centre.create', 'request_hash' => $hash, 'result' => json_encode($result, JSON_THROW_ON_ERROR), 'created_at' => now()]);
return $result;
});
return response()->json($result)->header('Cache-Control', 'private, no-store');
}
public function page(Request $request)
{
Installation::assertBudgetReady(DB::connection());
$ctx = app(CompanyContext::class);
$scope = $ctx->identifiers() + ['unit_id' => $ctx->unitId()];
$p = app(Permissions::class);
$actor = $request->user()->id;
$p->require($actor, $scope['tenant_id'], $scope['company_id'], 'purchasing_budget.view', $scope['unit_id']);
$contract = ['csrf' => csrf_token(), 'token' => $request->session()->get('company_context.token'), 'scope' => $scope, 'actor_id' => $actor,
'canCentre' => $p->has($actor, $scope['tenant_id'], $scope['company_id'], 'purchasing_requisitions.configure', $scope['unit_id']) && $p->has($actor, $scope['tenant_id'], $scope['company_id'], 'purchasing_budget.create', $scope['unit_id']),
'canPrepare' => $p->has($actor, $scope['tenant_id'], $scope['company_id'], 'purchasing_budget.create', $scope['unit_id']),
'canApprove' => $p->has($actor, $scope['tenant_id'], $scope['company_id'], 'purchasing_budget.approve', $scope['unit_id'])];
ob_start();
require __DIR__.'/budget-setup.php';
return response(ob_get_clean())->header('Cache-Control', 'private, no-store');
}
}