commit melhorias sgf
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Purchasing;
|
||||
|
||||
use App\Http\Requests\Sgc\StoreInvoiceRequest;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\{Crypt, DB};
|
||||
use Tempo\Finance\Payables\Payables;
|
||||
|
||||
/** Stateless transport to the existing pending-invoice workflow; no second business writer. */
|
||||
final class SgcInvoiceIngress
|
||||
{
|
||||
public function receive(StoreInvoiceRequest $request)
|
||||
{
|
||||
$body = $request->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);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user