16 lines
5.4 KiB
PHP
16 lines
5.4 KiB
PHP
<?php
|
|
use Illuminate\Support\Facades\Auth;use Illuminate\Support\Str;use App\Shared\Context\CompanyContext;use App\Modules\Services\{ReceivablePositionRead,ServiceReceivables};
|
|
require __DIR__.'/sgf-ledger-proof-bootstrap.php';set_exception_handler(function($e){echo json_encode(['passed'=>false,'type'=>get_class($e),'message'=>$e->getMessage()]).PHP_EOL;exit(1);});
|
|
$select=function($role,$module='finance')use($profiles,$app,$f){Auth::forgetGuards();Auth::shouldUse('web');$u=App\Models\User::findOrFail($profiles[$role]['user_id']);Auth::guard('web')->setUser($u);$r=Illuminate\Http\Request::create('/api/service-receivables/positions','GET');$r->attributes->set('sgf_module',$module);$r->setUserResolver(fn()=>$u);$session=app('session')->driver();$session->start();$session->put('company_context',$f['scope']+['module_id'=>$module,'token'=>'positions-'.$role]);$r->setLaravelSession($session);$app->instance('request',$r);app(CompanyContext::class)->selectFor($u->id,1,2,2);return$u->id;};
|
|
$reject=function($fn,$status,$label)use($ok){$actual=null;try{$fn();}catch(Symfony\Component\HttpKernel\Exception\HttpExceptionInterface$e){$actual=$e->getStatusCode();}catch(Illuminate\Validation\ValidationException){$actual=422;}$ok($actual===$status,$label);};$reader=app(ReceivablePositionRead::class);$query=['reference_on'=>'2026-11-10','per_page'=>100];$actor=$select('read_only');$before=[];foreach(['sr_records','sr_effects','sr_commands','permission_grants','si_invoices']as$t)$before[$t]=$host->table($t)->orderBy('id')->get()->toJson();
|
|
$out=$reader->listing($actor,$query);$ok($out['read_only']&&$out['balance_basis']==='current_confirmed_effects_not_historical_cut','current balance reference distinction');foreach($out['positions']->items()as$row){$state=app(ServiceReceivables::class)->position($row->id,$actor);$ok($row->state===$state['state']&&$row->due_date===$state['due_date']&&$row->allocated===$state['allocated']&&$row->reduced===$state['reduced']&&$row->revision===$state['revision']&&$row->balance===($state['opened']?$state['balance']:null),'authoritative position parity '.$row->id);}
|
|
$small=$reader->listing($actor,['reference_on'=>'2026-11-10','per_page'=>25]);$ok($small['positions']->pluck('id')->all()===$out['positions']->pluck('id')->all()&&count($out['positions']->items())<=25,'known universe same25 and100');$ok($reader->listing($actor,['reference_on'=>'2026-11-10','page'=>2])['positions']->count()===0,'out of range page empty without duplicate');$ok($reader->listing($actor,$query+['search'=>'%'])['positions']->total()===0,'literal wildcard not universe');$reject(fn()=>$reader->listing($actor,[]),422,'explicit reference date required');$reject(fn()=>$reader->listing($actor,$query+['company_id'=>3]),422,'company override refused');$reject(fn()=>$reader->listing($actor,['reference_on'=>'2026-11-10','per_page'=>1000]),422,'unbounded size refused');$reject(fn()=>$reader->listing($actor,$query+['state'=>'paid']),422,'unimplemented payment label refused');
|
|
$host->beginTransaction();try{
|
|
$commercial=json_decode(file_get_contents($s['root'].'/single-commercial.json'),true);$ob=$host->table('sr_records')->where(['invoice_id'=>$commercial['invoice'],'kind'=>'obligation'])->first();$ok((bool)$ob,'existing QA origin selected explicitly');$service=app(ServiceReceivables::class);
|
|
foreach([['2026-11-01','overdue',9],['2026-11-10','not_due',0],['2026-11-20','not_due',0],[null,'unknown',null]]as[$date,$expected,$days]){
|
|
$prepare=$select('finance_prepare');$revision=$host->table('sr_effects')->where('obligation_id',$ob->id)->count();$proposal=$service->propose($prepare,['kind'=>'correction','invoice_id'=>$ob->invoice_id,'obligation_id'=>$ob->id,'currency'=>'MZN','source'=>'SIM-POSITION-READ','external_id'=>(string)Str::uuid(),'action'=>'due','due_date'=>$date,'reason'=>'Conferência sintética de vencimento na regressão; rollback integral.','revision'=>$revision],(string)Str::uuid());$review=$select('finance_review');$service->decide($proposal['id'],$review,['version'=>1,'revision'=>$revision,'decision'=>'approved','reason'=>'Revisão distinta do vencimento exclusivamente na regressão.'],(string)Str::uuid());$read=$select('read_only');$position=collect($reader->listing($read,$query)['positions']->items())->firstWhere('id',$ob->id);$ok($position->due_state===$expected&&$position->overdue_days===$days,'due transition '.$expected.' '.($date??'null'));$filtered=$reader->listing($read,$query+['due_state'=>$expected]);$ok($filtered['positions']->getCollection()->contains('id',$ob->id),'SQL due filter '.$expected);$ok($position->balance===app(ServiceReceivables::class)->position($ob->id,$read)['balance'],'due correction does not change balance');
|
|
}
|
|
$select('commercial_prepare','commercial');$reject(fn()=>$reader->listing($profiles['commercial_prepare']['user_id'],$query),403,'other module refused');$read=$select('read_only');$reject(fn()=>$reader->listing($profiles['finance_prepare']['user_id'],$query),403,'actor mismatch refused');
|
|
}finally{while($host->transactionLevel()>0)$host->rollBack();}
|
|
foreach($before as$t=>$json)$ok($host->table($t)->orderBy('id')->get()->toJson()===$json,'original '.$t.' unchanged');file_put_contents($work.'/receivable-positions-result.json',json_encode(['passed'=>true,'checks'=>$checks,'new_rights'=>0,'test_due_corrections_rolled_back'=>true,'new_demo'=>false],JSON_PRETTY_PRINT));echo json_encode(['passed'=>true,'checks'=>count($checks),'proof'=>$work.'/receivable-positions-result.json']).PHP_EOL;
|