Files
Investidor-V2/tests/Feature/IrpcInternationalCreditDraftTest.php
2026-10-27 14:57:18 +02:00

63 lines
5.7 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IrpcInternationalCreditDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_international_credit_delta_round_trips_with_frozen_history_and_unchanged_existing_records(): void
{
$target=DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('proactive_investment_20261027_test',$target->name);
$this->assertSame(55441,(int)$target->port);
$snapshot=static fn(string $table):array=>collect(DB::select('select id::text as id,md5(row_to_json(t)::text) as hash from public."'.$table.'" t order by id'))->pluck('hash','id')->all();
$protected=[];
foreach(['opportunities','documents','opportunity_documents','simulation_form_drafts','users','organizations','audit_events']as$table)$protected[$table]=$snapshot($table);
config(['investor-path.enabled'=>true,'suitecrm.enabled'=>false]);
$this->actingAs(User::findOrFail(1021)); // Existing synthetic QA actor, no new grants.
$base=json_decode(file_get_contents(base_path('tests/frontend/fixtures/irpc-assessment-preserved.json')),true,flags:JSON_THROW_ON_ERROR);
$fixture=json_decode(file_get_contents(base_path('tests/frontend/fixtures/irpc-international-preserved.json')),true,flags:JSON_THROW_ON_ERROR);
$this->assertTrue($fixture['synthetic']);$this->assertFalse($fixture['actualConventionData']);
$personal=['person_type'=>$base['person_type']];unset($base['person_type']);
$id=null;$etag=null;$previous=null;
foreach($fixture['cases']as$name=>$book){
$draft=$base;$s=json_decode($draft['modelo_a_snapshot'],true,flags:JSON_THROW_ON_ERROR);
if($previous!==null)$book['history']=[$previous];
$s['irpcAnnual'][$draft['context_opportunity']]=$book;
$draft['modelo_a_snapshot']=json_encode($s,JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE);
$payload=['personal_snapshot'=>$personal,'economic_snapshot'=>$draft];
if($id===null)$id=$this->postJson('/api/v1/simulation-drafts',$payload,['Idempotency-Key'=>(string)Str::uuid()])->assertCreated()->json('data.id');
else $this->putJson('/api/v1/simulation-drafts/'.$id,$payload,['If-Match'=>$etag])->assertOk();
$response=$this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk();$etag=$response->headers->get('ETag');$back=$response->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'],$back['modelo_a_snapshot']);$this->assertSame($draft['business_plan_snapshot'],$back['business_plan_snapshot']);
$recovered=json_decode($back['modelo_a_snapshot'],true,flags:JSON_THROW_ON_ERROR);
foreach(['irpcNormal','irpcWithholdings','books','currencyEvents','ispcQuarters']as$map)$this->assertSame($s[$map],$recovered[$map]);
$saved=$recovered['irpcAnnual'][$draft['context_opportunity']];$m=$saved['result']['model'];$credit=$m['internationalCredit'];
$this->assertSame($book,$saved);$this->assertSame('IRPC-international-credit/1',$credit['version']);$this->assertFalse($credit['carryCreated']);$this->assertFalse($credit['officialBalancesConsumed']);$this->assertFalse($credit['countryAllocationCreated']);$this->assertFalse($m['submitted']);
$this->assertSame(['numerator'=>'1408','denominator'=>'1'],$m['assessment']['colecta']);
if(in_array($name,['missing','duplicate'],true)){
$this->assertSame('indeterminate',$m['status']);$this->assertNull($m['arithmeticBalance']);$this->assertNull($credit['deducted']);$this->assertNull($m['pecDeduction']['deducted']);$this->assertNotEmpty($m['pending']);
}else{
$expected=['payable'=>['payable','700','8','1400','200'],'treaty'=>['payable','702','6','1402','200'],'limited-collecta'=>['recoverable','-500','1408','0','0'],'absent'=>['payable','708','0','1408','200'],'prior-use'=>['payable','703','5','1403','200']][$name];
$this->assertSame($expected[0],$m['status']);$this->assertEmpty($m['pending']);
$this->assertSame(['numerator'=>$expected[1],'denominator'=>'1'],$m['arithmeticBalance']);
$this->assertSame(['numerator'=>$expected[2],'denominator'=>'1'],$credit['deducted']);
$this->assertSame(['numerator'=>$expected[3],'denominator'=>'1'],$credit['afterCredit']);
$this->assertSame(['numerator'=>$expected[4],'denominator'=>'1'],$m['pecDeduction']['deducted']);
if($name==='limited-collecta'){$this->assertSame(['numerator'=>'592','denominator'=>'1'],$credit['insufficientCollecta']);$this->assertSame(['numerator'=>'200','denominator'=>'1'],$m['pecDeduction']['remaining']);}
}
if($previous!==null)$this->assertSame($previous,$saved['history'][0]);$previous=$saved['result'];
if(getenv('INVESTMOZ_INTERNATIONAL_QA_OUTPUT')==='1')file_put_contents(base_path('outputs/irpc-l8-international-20261027/recovered-'.$name.'.json'),json_encode($back,JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE));
}
$preserved=[];
foreach($protected as$table=>$before){$this->assertSame($before,array_intersect_key($snapshot($table),$before),'Existing records changed: '.$table);$preserved[$table]=['existing_rows'=>count($before),'unchanged'=>true];}
if(getenv('INVESTMOZ_INTERNATIONAL_QA_OUTPUT')==='1')file_put_contents(base_path('outputs/irpc-l8-international-20261027/existing-records-preservation.json'),json_encode(['database'=>$target->name,'tables'=>$preserved,'transaction_rollback'=>true],JSON_THROW_ON_ERROR|JSON_PRETTY_PRINT));
}
}