validated(); $id = (int)$body['order_id']; $key = strtolower($request->header('X-Idempotency-Key')); $controller = app(InvoiceController::class); $runtime = app(ReceiptRuntime::class); $host = DB::connection(); abort_unless($host->getDriverName() === 'pgsql', 503); return $host->transaction(function () use ($request, $body, $id, $key, $controller, $runtime, $host) { // Serialize the complete retry check + native commit, including different orders using one key. $host->statement("SET LOCAL lock_timeout = '5s'"); $host->select('SELECT pg_advisory_xact_lock(hashtextextended(?, 0))', ['sgc.invoice:'.$key]); $controller->show($id, $runtime); // exact origin, current visibility and native policies if ($body['phase'] === 'confirm') { try { $cut = json_decode(Crypt::decryptString($body['preview']), true, 128, JSON_THROW_ON_ERROR); } catch (\Throwable) { abort(409, 'Prévia inválida.'); } abort_unless(($cut['action'] ?? null) === 'register' && ($cut['order_id'] ?? null) === $id && ($cut['operation_key'] ?? null) === $key, 409, 'Prévia de outra operação.'); $data = $cut['data']; $reason = $cut['reason']; } else { $cut = null; $data = $body['data']; $reason = $body['reason']; } $hash = hash('sha256', Payables::canonical([[$id, 'register', $data, $reason]])); $generation = hash('sha256', Payables::canonical([$request->session()->get('company_context')])); $old = $runtime->run('purchasing_invoices.prepare', function ($actor, $binding, $fingerprint) use ($key, $id, $hash, $cut, $generation) { $actor = app(\Tempo\Purchasing\Embedded\Services\CurrentActor::class)->lock($actor, ['finance']); abort_if(app(\Tempo\Purchasing\Embedded\Services\OrganizationAccess::class)->maintenanceOnly($actor), 403); if ($cut) abort_unless(($cut['actor'] ?? null) === $actor->id && ($cut['binding'] ?? null) === $fingerprint && ($cut['generation'] ?? null) === $generation, 409, 'Contexto da prévia alterado.'); $receipt = \Tempo\Purchasing\Embedded\Models\AuditLog::where('user_id', $actor->id) ->where('action', 'sgf.invoice.command')->where('after->operation_key', $key)->first(); if (!$receipt) return null; abort_unless(($receipt->after['result']['order_id'] ?? null) === $id && ($receipt->after['request_hash'] ?? null) === $hash && ($receipt->after['binding_revision'] ?? null) === $fingerprint, 409, 'Chave usada com outro conteúdo ou origem.'); return $receipt->after['result'] + ['replayed'=>true]; }); if ($old) return response()->json($old); $input = $body['phase'] === 'confirm' ? ['preview'=>$body['preview']] : ['operation_key'=>$key, 'revision'=>$body['revision'], 'action'=>'register', 'reason'=>$reason, 'data'=>$data]; $native = Request::create('/api/purchasing-invoices/'.$id, 'POST', $input, [], [], ['HTTP_ACCEPT'=>'application/json']); $native->setLaravelSession($request->session()); $native->setUserResolver($request->getUserResolver()); return $body['phase'] === 'confirm' ? $controller->confirm($id, $native, $runtime) : $controller->preview($id, $native, $runtime); }); } }