Accept isolated invoice issuance and reproducible PDF delivery
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\Process\Process;
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
$app=require __DIR__.'/../bootstrap/app.php'; $app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
\App\Modules\Services\ServiceInvoicing::guard();
|
||||
$f=json_decode(file_get_contents('C:/laragon/data/sgf-tempo/secrets/browser-fixture.json'),true,32,JSON_THROW_ON_ERROR);
|
||||
$fixture=$f+$f['invoice']+['manager'=>\App\Models\User::findOrFail($f['manager_id']),'reader'=>\App\Models\User::findOrFail($f['reader_id'])];
|
||||
$fixture=DB::transaction(fn()=>\Tests\Support\InvoiceFixture::additionalDraft($fixture));
|
||||
$review=app(\App\Modules\Services\ServiceInvoicing::class)->review($fixture['draft'],$fixture['series'],$fixture['rule'],$f['manager_id']);
|
||||
if(!$review['ready']) throw new RuntimeException('Synthetic concurrent revision not ready.');
|
||||
$input=['actor'=>$f['manager_id'],'tenant'=>$f['tenant'],'company'=>$f['company'],'unit'=>$f['unit'],'draft'=>$fixture['draft'],'key'=>(string)\Illuminate\Support\Str::uuid(),'input'=>['series_id'=>$fixture['series'],'rule_id'=>$fixture['rule'],'review_hash'=>$review['review_hash']]];
|
||||
$before=DB::table('si_invoices')->count();
|
||||
$a=new Process([PHP_BINARY,'scripts/invoice-worker.php','--env=testing'],base_path(),null,json_encode($input+['pause'=>true]));
|
||||
$b=new Process([PHP_BINARY,'scripts/invoice-worker.php','--env=testing'],base_path(),null,json_encode($input));
|
||||
$a->start();if(!$a->waitUntil(fn($type,$buffer)=>str_contains($buffer,'LOCK_HELD')))throw new RuntimeException('No overlapping lock established.');
|
||||
$b->start();$a->wait();$b->wait();$results=[];
|
||||
foreach([$a,$b] as $p){if(!$p->isSuccessful())throw new RuntimeException('Synthetic worker failed.');$lines=array_values(array_filter(explode("\n",trim($p->getOutput())),fn($s)=>str_starts_with($s,'{')));$results[]=json_decode(end($lines),true,32,JSON_THROW_ON_ERROR);}
|
||||
if($results[0]['id']!==$results[1]['id'] || $results[0]['replayed'] || !$results[1]['replayed'] || DB::table('si_invoices')->count()!==$before+1)throw new RuntimeException('Duplicate or missing concurrent invoice.');
|
||||
if(DB::table('si_invoices')->distinct()->count('number')!==DB::table('si_invoices')->count())throw new RuntimeException('Series number repeated.');
|
||||
file_put_contents(base_path('docs/proofs/invoice-concurrency.json'),json_encode(['database'=>'sgf_tempo_test','overlapping_processes'=>2,'one_invoice_one_replay'=>true,'numbers_distinct_in_shared_series'=>true,'prior_documents_preserved'=>true],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
|
||||
echo "Concurrent synthetic issuance verified: one invoice, one replay, shared series without duplicate number.\n";
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
$app=require __DIR__.'/../bootstrap/app.php'; $app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
\App\Modules\Services\ServiceInvoicing::guard();
|
||||
$f=json_decode(file_get_contents('C:/laragon/data/sgf-tempo/secrets/browser-fixture.json'),true,32,JSON_THROW_ON_ERROR);
|
||||
$fixture=$f+$f['invoice']+['manager'=>\App\Models\User::findOrFail($f['manager_id']),'reader'=>\App\Models\User::findOrFail($f['reader_id'])];
|
||||
$fixture=\Illuminate\Support\Facades\DB::transaction(fn()=>\Tests\Support\InvoiceFixture::additionalDraft($fixture));
|
||||
$issuer=app(\App\Modules\Services\ServiceInvoicing::class);
|
||||
$review=$issuer->review($fixture['draft'],$fixture['series'],$fixture['rule'],$f['manager_id']);
|
||||
if(!$review['ready'])throw new RuntimeException('Synthetic export revision not ready.');
|
||||
$result=$issuer->issue($fixture['draft'],$f['manager_id'],['series_id'=>$fixture['series'],'rule_id'=>$fixture['rule'],'review_hash'=>$review['review_hash']],(string)\Illuminate\Support\Str::uuid());
|
||||
$pdf=$issuer->pdf($result['id'],$f['manager_id']);
|
||||
$dir=base_path('output/pdf'); if(!is_dir($dir))mkdir($dir,0777,true);
|
||||
file_put_contents($dir.'/sgf-tempo-factura-teste.pdf',$pdf);
|
||||
$view=$issuer->show($result['id'],$f['manager_id']);
|
||||
$long=$view['snapshot']; unset($long['document_lines']); $long['document']['observations']=str_repeat('Conteúdo sintético extenso para verificar paginação e margens. ',80).str_repeat('W',800);
|
||||
file_put_contents(storage_path('app/invoice-long-proof.pdf'),app(\App\Modules\Services\InvoicePdf::class)->render($long));
|
||||
if($pdf!==$issuer->pdf($result['id'],$f['manager_id']))throw new RuntimeException('PDF bytes changed.');
|
||||
file_put_contents(base_path('docs/proofs/invoice-pdf-results.json'),json_encode(['database'=>'sgf_tempo_test','renderer'=>$view['snapshot']['renderer'],'pdf_sha256'=>hash('sha256',$pdf),'repeated_download_identical'=>true,'browser_and_pdf_share_document_lines'=>true,'synthetic_only'=>true],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
|
||||
echo json_encode(['invoice_id'=>$result['id'],'number'=>$result['number'],'pdf_sha256'=>hash('sha256',$pdf),'renderer'=>$view['snapshot']['renderer']],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR).PHP_EOL;
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
$app=require __DIR__.'/../bootstrap/app.php'; $app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
\App\Modules\Services\ServiceInvoicing::guard();
|
||||
$file='C:/laragon/data/sgf-tempo/secrets/browser-fixture.json';
|
||||
$f=json_decode(file_get_contents($file),true,32,JSON_THROW_ON_ERROR);
|
||||
if(\Illuminate\Support\Facades\DB::table('a_services')->exists() || \Illuminate\Support\Facades\DB::table('si_proposals')->exists()) throw new RuntimeException('Synthetic fixture must be empty; nothing deleted.');
|
||||
$fixture=\Illuminate\Support\Facades\DB::transaction(fn()=>\Tests\Support\InvoiceFixture::create($f+['manager'=>\App\Models\User::findOrFail($f['manager_id']),'reader'=>\App\Models\User::findOrFail($f['reader_id'])]));
|
||||
$ids=array_intersect_key($fixture,array_flip(['client','service','source','draft','profile','temporal','calculation','series','rule','today','start','end']));
|
||||
file_put_contents($file,json_encode($f+['invoice'=>$ids],JSON_THROW_ON_ERROR));
|
||||
echo "Synthetic invoice fixture ready only in sgf_tempo_test; no invoice or PDF pre-issued.\n";
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
$app=require __DIR__.'/../bootstrap/app.php'; $app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
\App\Modules\Services\ServiceInvoicing::guard();
|
||||
$in=json_decode(stream_get_contents(STDIN),true,32,JSON_THROW_ON_ERROR);
|
||||
app(\App\Shared\Context\CompanyContext::class)->selectFor($in['actor'],$in['tenant'],$in['company'],$in['unit']);
|
||||
if($in['pause'] ?? false) { $paused=false; \Illuminate\Support\Facades\DB::listen(function($q)use(&$paused){if(!$paused && str_contains($q->sql,'"companies"') && str_contains($q->sql,'for update')){$paused=true;echo "LOCK_HELD\n";flush();usleep(1500000);}}); }
|
||||
echo json_encode(app(\App\Modules\Services\ServiceInvoicing::class)->issue($in['draft'],$in['actor'],$in['input'],$in['key']),JSON_THROW_ON_ERROR).PHP_EOL;
|
||||
Reference in New Issue
Block a user