Files
SGF/scripts/sgf-assets-writeoff-close-proof.php
2026-11-11 15:04:01 +02:00

10 lines
5.2 KiB
PHP

<?php
require __DIR__.'/sgf-assets-proof-bootstrap.php';$host->beginTransaction();$native->beginTransaction();try{
$keys=[];foreach(['asset','plan','charge','disposal']as$k)$keys[$k]=(string)Str::uuid();$a=['operation'=>'establish','code'=>'QA-WRITEOFF-ROLLBACK','description'=>'Activo artificial para abate100 e1100 revertido','origin_reference'=>'QA-WRITEOFF-OPEN-ROLLBACK','cost'=>'1200.00','residual'=>'0.00','available_on'=>'2026-10-01','location'=>'QA-SALA-A','custodian'=>'QA-CUSTODIA-A','evidence'=>'Abate100 acumulado e1100 perda, fixture revertida.'];$admin=function($kind,$input)use($faCommand,$faInput,$keys){$faCommand(15,$faInput($kind,$keys[$kind],0,$input));return$faCommand(16,$faInput($kind,$keys[$kind],1,['decision'=>'approved'],'review'))[0];};$gl=function($kind,$id,$on,$rule)use($call){$p=$call('accounting_prepare','prepare',fn($e)=>$e->command('effect-prepare',['effect_type'=>$kind,'source_id'=>$id,'journal_on'=>$on,'period_key'=>'QA-2026-INTEGRADO','rule_key'=>$rule,'reason'=>'Conferência de activo no recorte QA revertido.'],(string)Str::uuid()));$call('accounting_review','validate',fn($e)=>$e->command('validate',['proposal_id'=>$p['proposal_id'],'revision'=>$p['revision'],'decision'=>'approved','reason'=>'Revisão distinta do activo no recorte QA revertido.'],(string)Str::uuid()));return$call('accounting_prepare','post',fn($e)=>$e->command('post',['proposal_id'=>$p['proposal_id'],'revision'=>$p['revision'],'reason'=>'Aplicação do activo no recorte QA revertido.'],(string)Str::uuid()));};$ar=$admin('asset',$a);$gl('assets.admitted',$ar['id'],'2026-10-01','QA-ASSET-ADMISSION');$admin('plan',['operation'=>'establish','asset_key'=>$keys['asset'],'life_months'=>12,'status'=>'active','evidence'=>'Plano linear artificial de12 meses para abate.']);$cr=$admin('charge',['operation'=>'establish','asset_key'=>$keys['asset'],'plan_key'=>$keys['plan'],'month'=>'2026-10','evidence'=>'Quota100 artificial Outubro para abate.']);$gl('assets.depreciation',$cr['id'],'2026-10-31','QA-ASSET-DEPRECIATION');$dr=$admin('disposal',['operation'=>'establish','asset_key'=>$keys['asset'],'effect_on'=>'2026-11-01','evidence'=>'Abate artificial sem contraprestação, saldo1100.']);$dj=$gl('assets.writeoff',$dr['id'],'2026-11-01','QA-ASSET-WRITEOFF');$lines=$native->table('gl_lines')->where('journal_id',$dj['journal_id'])->orderBy('line_no')->get();$ok($lines->count()===3&&$lines[0]->debit_minor===10000&&$lines[1]->debit_minor===110000&&$lines[2]->credit_minor===120000,'specified writeoff accumulated100 loss1100 cost1200');foreach($native->table('gl_journals')->where('snapshot->source->asset_key',$keys['asset'])->pluck('id')as$id)$native->select('SELECT gl_assert_balanced(?)',[$id]);$ok(true,'all three synthetic journals balanced');
// Isolate this asset conference from unrelated financial fixtures in the regression harness only.
// Neither production bridge nor existing financial source mappings are changed.
$concurrency=json_decode(file_get_contents($s['root'].'/assets-concurrency-1794388203631/cuts-private.json'),true);$r=$host->table('fa_versions')->where('record_key',$concurrency['record_key'])->where('state','approved')->first();$d=json_decode($r->data,true)['input'];$d['operation']='cancel';$faCommand(15,$faInput('asset',$r->record_key,2,$d));$faCommand(16,$faInput('asset',$r->record_key,3,['decision'=>'approved'],'review'));
$run=function($role,$right,$command,$input)use($call,$native){return$call($role,$right,function($e,$actor,$b,$o,$scope,$stock,$hostRead)use($native,$command,$input){(new ReflectionProperty($e,'financialScope'))->setValue($e,$scope);(new ReflectionProperty($e,'additionalPeriod'))->setValue($e,fn($p)=>$hostRead(fn()=>app(App\Modules\Accounting\FixedAssetLedgerSource::class)->period(App\Models\User::findOrFail($o['sgf_host_user']),$p,$native,$scope)));return$e->command($command,$input,(string)Str::uuid());});};
$p=$run('accounting_prepare','period_prepare','period-prepare',['period_key'=>'QA-2026-INTEGRADO','reason'=>'Conferência do recorte de activos QA no harness revertido.']);$run('accounting_review','period_validate','period-validate',['check_id'=>$p['check_id'],'revision'=>$p['revision'],'decision'=>'approved','reason'=>'Revisão distinta do recorte de activos no harness.']);$out=$run('accounting_prepare','period_close','period-close',['check_id'=>$p['check_id'],'revision'=>$p['revision'],'reason'=>'Fecho apenas do recorte sintético de activos revertido.']);$ok($out['state']==='closed','asset scope period can close after distinct review');$ok($native->table('gl_periods')->where($f['scope'])->orderByDesc('version')->value('status')==='closed','closed version observable inside rollback');
}finally{$native->rollBack();$host->rollBack();}$ok($native->table('gl_periods')->where($f['scope'])->orderByDesc('version')->value('status')==='open','regression period remains open after rollback');file_put_contents($work.'/assets-writeoff-close.json',json_encode(['passed'=>true,'checks'=>$checks,'regression_only'=>true,'all_fixtures_rolled_back'=>true,'period_harness'=>'asset-only additional period callback and qualified empty financial fixture scope; not full application closure','real_http_closure'=>false],JSON_PRETTY_PRINT));echo json_encode(['passed'=>true,'checks'=>count($checks),'proof'=>$work.'/assets-writeoff-close.json']).PHP_EOL;