15 lines
6.3 KiB
PHP
15 lines
6.3 KiB
PHP
<?php
|
|
use Illuminate\Support\Facades\{DB,Crypt};
|
|
require __DIR__.'/sgf-bank-proof-bootstrap.php';$before=[];foreach(['br_statements','br_events','br_commands','fx_versions','fr_events','fr_calculations','si_invoices','sr_effects','cash_events']as$t)$before[$t]=$host->table($t)->orderBy('id')->get()->toJson();$nativeBefore=$native->table('gl_journals')->orderBy('id')->get()->toJson();$host->beginTransaction();try{
|
|
$selectBank(13);$state=$bank->listing(13,[]);$v=$state['version'];$ok($state['source_kind']==='regression_harness_fixture','fixture source explicitly identified not actual ledger');$p=$bankPreview(13,$bankInput('import',$v,$importData));$ok($host->table('br_statements')->orderBy('id')->get()->toJson()===$before['br_statements'],'import preview leaves no header');$reject(fn()=>$bankPreview(17,$bankInput('import',$v,$importData)),403,'read-only import refused');$reject(fn()=>$bankPreview(13,$bankInput('import',$v,array_replace($importData,['currency'=>'USD']))),422,'currency mismatch refused');$reject(fn()=>$bankPreview(13,$bankInput('import',$v,array_replace($importData,['csv'=>str_replace('20.00','21.00',$importData['csv'])]))),422,'amount/balance mismatch refused');
|
|
$selectBank(13);$imported=$bank->confirm(13,$p['preview']);$again=$bank->confirm(13,$p['preview']);$ok($again['replayed']&&$again['id']===$imported['id'],'same import key no duplicate header or rows');$reject(fn()=>$bankPreview(13,$bankInput('prepare_match',$v+1,['row_reference'=>'QA-OUT-20','ledger_line_id'=>4])),409,'unreviewed statement blocks matching');$reject(fn()=>$bankPreview(13,$bankInput('review_statement',$v+1,['decision'=>'reviewed'])),403,'importer cannot review');
|
|
[$review]=$bankCommand(14,$bankInput('review_statement',$v+1,['decision'=>'reviewed']));$ok($review['state']==='statement_reviewed','different person reviews exact statement');$reject(fn()=>$bankPreview(14,$bankInput('finalize',$v+2,[])),409,'incomplete statement not finalized');$reject(fn()=>$bankPreview(13,$bankInput('prepare_match',$v+2,['row_reference'=>'QA-OUT-20','ledger_line_id'=>5])),422,'same amount wrong direction refused');$reject(fn()=>$bankPreview(13,$bankInput('prepare_match',$v+2,['row_reference'=>'QA-OUT-20','ledger_line_id'=>999])),403,'unbound ledger line refused');
|
|
[$match]=$bankCommand(13,$bankInput('prepare_match',$v+2,['row_reference'=>'QA-OUT-20','ledger_line_id'=>4]));$reject(fn()=>$bankPreview(13,$bankInput('prepare_match',$v+3,['row_reference'=>'QA-OUT-20','ledger_line_id'=>4])),409,'pending row cannot receive another proposal');$a=$bankPreview(14,$bankInput('review_match',$v+3,['decision'=>'reviewed'],$match['id']));$b2=$bankPreview(14,$bankInput('review_match',$v+3,['decision'=>'reviewed'],$match['id']));$selectBank(14);$out=$bank->confirm(14,$a['preview']);$reject(fn()=>$bank->confirm(14,$b2['preview']),409,'second stale review refused');$reject(fn()=>$bankPreview(13,$bankInput('prepare_match',$v+4,['row_reference'=>'QA-OUT-20','ledger_line_id'=>4])),409,'confirmed ledger/statement row cannot be reused');
|
|
[$match2]=$bankCommand(13,$bankInput('prepare_match',$v+4,['row_reference'=>'QA-IN-20','ledger_line_id'=>5]));[$review2]=$bankCommand(14,$bankInput('review_match',$v+5,['decision'=>'reviewed'],$match2['id']));$selectBank(17);$state=$bank->listing(17,['status'=>'matched']);$ok(count($state['rows'])===2&&$state['statement']['closing_minor']===0&&!$state['report_available'],'both rows individually reviewed, report still not final');$reject(fn()=>$bank->report(17),409,'pre-final report not available');[$final]=$bankCommand(14,$bankInput('finalize',$v+6,[]));$ok($final['state']==='finalized'&&$final['impact']['data']['difference_minor']===0,'final conference zero difference');$selectBank(17);$report=$bank->report(17);$ok(hash('sha256',$report['bytes'])===$report['sha256']&&str_contains($report['bytes'],'NAO E EXTRACTO BANCARIO REAL')&&str_contains($report['bytes'],'QA-OUT-20;4;2'),'report recovers exact explicit correspondences');$reject(fn()=>$bankPreview(13,$bankInput('prepare_match',$v+7,['row_reference'=>'QA-IN-20','ledger_line_id'=>5])),409,'finalized book cannot be reopened');
|
|
[$same]=$bankCommand(13,$bankInput('import',$v+7,$importData));$ok($same['already_imported']&&$host->table('br_events')->count()===7,'same CSV under new key returns same finalized statement without events');$selectBank(13);$key=$host->table('br_commands')->where('actor_id',13)->orderBy('id')->value('command_key');$ok($bank->receipt(13,$key)['operation_executed']===false,'own receipt read does not execute');$selectBank(14);$reject(fn()=>$bank->receipt(14,$key),404,'other actor cannot recover key');
|
|
$fakeSource->changed=true;$selectBank(17);$blocked=$bank->listing(17,[]);$ok($blocked['blocked']!==null&&!$blocked['report_available']&&$blocked['source_lines']===[],'changed source blocks report without creating zero balance');$reject(fn()=>$bank->report(17),409,'changed source requires new conference');$fakeSource->changed=false;
|
|
}finally{$host->rollBack();}
|
|
// New import, inject receipt failure and recover. No accepted statement is edited.
|
|
$host->beginTransaction();try{$p=$bankPreview(13,$bankInput('import',0,$importData));$host->beginTransaction();try{$host->statement("CREATE FUNCTION br_fail_test() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'Injected bank failure'; END; $$");$host->statement('CREATE TRIGGER br_fail_test BEFORE INSERT ON br_commands FOR EACH ROW EXECUTE FUNCTION br_fail_test()');$selectBank(13);$failed=false;try{$bank->confirm(13,$p['preview']);}catch(Illuminate\Database\QueryException){$failed=true;}$ok($failed&&$host->table('br_statements')->count()===0&&$host->table('br_events')->count()===0,'failed receipt insertion rolls back import/header/event');}finally{$host->rollBack();}$selectBank(13);$success=$bank->confirm(13,$p['preview']);$ok($success['state']==='imported','same import command recovers after failure');}finally{$host->rollBack();}
|
|
foreach($before as$t=>$json)$ok($host->table($t)->orderBy('id')->get()->toJson()===$json,'unchanged '.$t);$ok($native->table('gl_journals')->orderBy('id')->get()->toJson()===$nativeBefore,'native ledger untouched');file_put_contents($work.'/bank-result.json',json_encode(['passed'=>true,'checks'=>$checks,'origin_simulated_in_harness'=>true,'rolled_back'=>true,'new_financial_effects'=>0,'new_demo'=>false],JSON_PRETTY_PRINT));echo json_encode(['passed'=>true,'checks'=>count($checks),'proof'=>$work.'/bank-result.json']).PHP_EOL;
|