Files
Investidor-V2/tools/portal-functional-lease-workflow-persistence-qa.php
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

32 lines
5.6 KiB
PHP

<?php
// SQL correspondence for the remaining lease branch, with historical bytes untouched.
use App\Models\Opportunity;
use App\Models\User;
use App\Services\OpportunityCanonicalContract;
use App\Services\OpportunityManagement;
use App\Services\PortalProfileAccess;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
$root=dirname(__DIR__);$dir=$root.'/storage/app/private/investmoz-v2/portal-audit';
$ui=json_decode(file_get_contents($dir.'/functional-lease-workflow-chromium-20261011.json'),true,512,JSON_THROW_ON_ERROR);
if(($ui['result']??null)!=='passed'||$ui['opportunity_id']!==54)throw new RuntimeException('Complete Chromium lease proof required.');
$plan=json_decode(file_get_contents($dir.'/portal-stability-latest.json'),true,512,JSON_THROW_ON_ERROR);
putenv('STABILITY_QA_MODE=consumers');$app=(static fn($p)=>require $p)($plan['source'].'/tools/portal-stability-runtime.php');
$target=DB::selectOne('select current_database() as database,inet_server_port() as port');
throw_unless($target->database==='stability_consumers_20261011_084534_test'&&(int)$target->port===55441,RuntimeException::class,'Exact isolated QA required.');
$proof=DB::transaction(function()use($ui,$dir,$target){DB::statement('SET TRANSACTION READ ONLY');
$record=Opportunity::findOrFail(54);$contract=app(OpportunityCanonicalContract::class)->validateSubmission($record);$p=$contract['payload'];$c=$record->workflow_context;
throw_unless($p['real_estate']['transaction_type']==='lease'&&$p['real_estate']['rent']===4500&&$p['real_estate']['rent_periodicity']==='monthly'&&$p['currency']==='MZN',RuntimeException::class,'Lease amount/periodicity/currency differ.');
throw_unless(app(PortalProfileAccess::class)->state($record)==='published'&&$contract['hash']===$c['approval']['hash']&&$contract['hash']===$c['publication']['hash']&&$c['approval']['actor_id']===24&&$c['publication']['actor_id']===25,RuntimeException::class,'Independent signed publication differs.');
throw_unless(! $record->publicationPresentation()['public_catalog'],RuntimeException::class,'Only restricted publication permitted.');
$events=DB::table('audit_events')->where('source_system','portal-profiles-v1')->where('after_data->record_id',54)->orderBy('occurred_at')->get(['action','actor_user_id','occurred_at','after_data'])->map(function($r){$d=json_decode($r->after_data,true,512,JSON_THROW_ON_ERROR);return ['action'=>$r->action,'actor'=>(int)$r->actor_user_id,'at'=>$r->occurred_at,'before'=>$d['before']??null,'after'=>$d['after']??null,'reason_recorded'=>!empty($d['reason'])];})->all();
$sequence=array_column($events,'action');foreach(['workflow_submit','workflow_request_correction','workflow_review_gate','workflow_approve','workflow_publish']as$action)throw_unless(in_array($action,$sequence,true),RuntimeException::class,'Lease transition audit missing.');
$edits=[];foreach(DB::table('audit_events')->where('source_system','opportunity-management')->where('after_data->record_id',54)->orderBy('occurred_at')->get(['action','after_data'])as$row){$a=json_decode($row->after_data,true,512,JSON_THROW_ON_ERROR);$raw=json_decode(Crypt::decryptString($a['snapshot']),true,512,JSON_THROW_ON_ERROR);$o=new Opportunity;$o->setRawAttributes($raw,true);$payload=app(OpportunityManagement::class)->values($o)['canonical']??[];$re=$payload['real_estate']??[];if(!isset($re['rent']))continue;throw_unless($re['rent']===4500&&$re['rent_periodicity']==='monthly',RuntimeException::class,'Persisted edit changed the demonstrated amount.');$edits[]=['action'=>$row->action,'version'=>$a['version'],'rent'=>4500,'periodicity'=>'monthly'];}
$documents=[];foreach($ui['documents']as$kind=>$proof){$r=DB::table('opportunity_documents')->where('id',$proof['id'])->first();$d=DB::table('documents')->where('id',$r->document_id)->first();throw_unless((int)$r->opportunity_id===54&&!$r->deleted_at&&$d->sha256===$proof['sha256']&&$d->malware_scan_status==='clean'&&$d->malware_scanned_sha256===$d->sha256,RuntimeException::class,'Own document integrity/scan mismatch.');$documents[]=['kind'=>$kind,'resource_id'=>$r->id,'document_id'=>$d->id,'sha256'=>$d->sha256,'scan'=>$d->malware_scan_status,'encryption'=>$d->storage_encryption];}
$old=json_decode(file_get_contents($dir.'/functional-final-persistence-qa-20261011.json'),true,512,JSON_THROW_ON_ERROR);foreach($old['categories']as$prior){$o=Opportunity::findOrFail($prior['id']);throw_unless($o->management_version===$prior['version']&&($o->workflow_context['publication']['hash']??null)===$prior['publication_hash'],RuntimeException::class,'Prior six-category evidence invalidated.');}
$health=app(App\Services\Malware\MalwareScanner::class)->health();
return ['result'=>'passed','at'=>gmdate('c'),'target'=>$target,'id'=>54,'state'=>'published','scope'=>$record->publicationPresentation(),'rent'=>4500,'rent_periodicity'=>'monthly','currency'=>'MZN','version'=>$record->management_version,'hash'=>$contract['hash'],'approval_actor'=>24,'publication_actor'=>25,'events'=>$events,'edit_snapshots'=>$edits,'browser_transitions_preserve_rent'=>count($ui['transitions']),'documents'=>$documents,'outside_organization_denied'=>!app(PortalProfileAccess::class)->canView(User::findOrFail(23),$record),'six_prior_categories_unchanged'=>true,'ClamD_real'=>$health,'active_writes'=>0];
});
file_put_contents($dir.'/functional-lease-workflow-persistence-qa-20261011.json',json_encode($proof,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_THROW_ON_ERROR));
echo json_encode(array_intersect_key($proof,array_flip(['result','id','state','rent','rent_periodicity','currency','approval_actor','publication_actor','browser_transitions_preserve_rent','six_prior_categories_unchanged','active_writes'])),JSON_THROW_ON_ERROR).PHP_EOL;