Accept conditional service calculation with versioned fiscal profile

This commit is contained in:
2026-10-26 16:48:44 +02:00
parent bc2707bb65
commit 9f480045fa
25 changed files with 801 additions and 3 deletions
+12 -2
View File
@@ -18,6 +18,15 @@ final class ServiceCalculation
public static function isolated(): bool { return app()->environment(['testing','browser-testing']); }
public static function evaluateReal(array $data, array $prepared, array $profile): array
{
abort_unless(($profile['kind'] ?? null)==='real',422,'Perfil real identificado obrigatório.');
// Shared decimal arithmetic; authority/applicability is checked by ServiceFiscal before calling.
$result=self::evaluate($data,$prepared,array_replace($profile,['kind'=>'synthetic']));
if ($result['state']!=='pending') $result['state']='real_proposed_conditioned';
return $result;
}
public static function evaluate(array $data, array $prepared, ?array $profile): array
{
$pending = [];
@@ -97,14 +106,15 @@ final class ServiceCalculation
public function read(int $draft, int $actor): array
{
$scope = $this->workflow->scope('billing_drafts',$actor,'view');
if (!self::isolated()) { return ['environment'=>'normal','history'=>[], 'pending'=>['Aplicabilidade à empresa, serviço/localização, base e acontecimento fiscal por demonstrar; nenhum perfil real activado.']]; }
if (!self::isolated()) { return ['environment'=>'normal','history'=>[], 'pending'=>['O cálculo proposto requer perfil aprovado, activo e compatível e decisão temporal aprovada. Consulte o resultado e as pendências abaixo, quando disponíveis.']]; }
TestingDatabaseGuard::assertSafe();
[$b,$p] = $this->sources($draft,$actor);
$profiles = DB::table('service_calculation_profiles')->where($scope)->orderByDesc('version')->get();
$profiles = DB::table('service_calculation_profiles')->where($scope)->whereRaw("definition->>'kind' = ?",['synthetic'])->orderByDesc('version')->get();
$latest = []; foreach ($profiles as $profile) { $latest[$profile->identifier] ??= $profile; }
$history = [];
foreach (DB::table('service_calculation_results')->where($scope)->where('billing_draft_id',$draft)->orderByDesc('id')->get() as $row) {
$snapshot = json_decode($row->snapshot,true,32,JSON_THROW_ON_ERROR);
if (isset($snapshot['input']['profile_proposal_id'])) continue;
$profile = $latest[$snapshot['input']['profile_identifier']] ?? null;
$current = $profile && hash_equals($row->fingerprint,$this->fingerprint($this->input($b,$p,$profile)));
$history[] = ['id'=>$row->id,'current'=>(bool)$current,'snapshot'=>$snapshot];