true,'bank_qa.binding_sha256'=>hash_file('sha256',$s['root'].'/bank-binding.json')]); if($book!=='regression')throw new LogicException('Injected source only in regression harness'); $fakeSource=new class extends BankLedgerSource{public bool $changed=false;public function snapshot(array $scope,array $binding):array{if($scope!==['tenant_id'=>1,'company_id'=>2,'unit_id'=>2]||$binding['composition']!=='b4093c6f6707')throw new LogicException('Regression fixture scope');$rows=[['id'=>4,'journal_id'=>2,'account_code'=>'QA-LIQUIDACAO','date'=>'2026-11-10','currency'=>'MZN','debit_minor'=>0,'credit_minor'=>2000,'journal_sha256'=>str_repeat($this->changed?'c':'a',64)],['id'=>5,'journal_id'=>3,'account_code'=>'QA-LIQUIDACAO','date'=>'2026-11-10','currency'=>'MZN','debit_minor'=>2000,'credit_minor'=>0,'journal_sha256'=>str_repeat('b',64)]];return ['kind'=>'regression_harness_fixture','lines'=>$rows,'hash'=>hash('sha256',Tempo\Finance\Payables\Payables::canonical($rows))];}}; $app->instance(BankLedgerSource::class,$fakeSource);$bank=app(BankReconciliation::class); $selectBank=function($actor=13,$generation='bank-proof')use($app){Auth::forgetGuards();Auth::shouldUse('web');$user=App\Models\User::findOrFail($actor);Auth::guard('web')->setUser($user);$session=app('session')->driver();$session->start();$session->put('company_context',['tenant_id'=>1,'company_id'=>2,'unit_id'=>2,'module_id'=>'finance','token'=>$generation.'-'.$actor]);$r=Illuminate\Http\Request::create('/api/bank-reconciliation','POST');$r->setUserResolver(fn()=>$user);$r->setLaravelSession($session);$r->attributes->set('sgf_module','finance');$app->instance('request',$r);app(CompanyContext::class)->selectFor($actor,1,2,2);return $actor;}; $importData=['account_ref'=>'QA-BANCO-LOCAL','currency'=>'MZN','period'=>'2026-11','opening'=>'0.00','closing'=>'0.00','csv'=>file_get_contents($repo.'/resources/data/bank-statement-qa.csv')]; $bankInput=fn($action,$version,$data=[],$proposal=null)=>['action'=>$action,'version'=>$version,...($proposal?['proposal_id'=>$proposal]:[]),'data'=>$data,'reason'=>'Conferência individual QA de extracto, origem, sinais e versão, sem efeito financeiro.']; $bankPreview=function($actor,$in,$key=null)use($bank,$selectBank){$selectBank($actor);return $bank->preview($actor,$in,$key??(string)Str::uuid());}; $bankCommand=function($actor,$in)use($bank,$bankPreview,$selectBank){$p=$bankPreview($actor,$in);$selectBank($actor);return [$bank->confirm($actor,$p['preview']),$p];}; $reject=function($fn,$status,$name)use($ok){try{$fn();throw new RuntimeException('Expected refusal: '.$name);}catch(Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $e){$ok($e->getStatusCode()===$status,$name);}catch(Illuminate\Validation\ValidationException){$ok($status===422,$name);}};