67 lines
3.9 KiB
PHP
67 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use Brick\Math\BigRational;
|
|
|
|
/** Shared snapshot representation; eligibility is resolved by each admission adapter. */
|
|
final class SimulationFiscalSnapshot
|
|
{
|
|
/**
|
|
* @param array<array-key, mixed>|null $evaluation
|
|
* @param array<array-key, mixed> $input
|
|
* @param array<array-key, mixed> $missing
|
|
* @param array<array-key, mixed> $resolution
|
|
* @param array<array-key, mixed> $version
|
|
* @return array<array-key, mixed>
|
|
*/
|
|
public function build(array $version, array $input, array $resolution, ?array $evaluation, array $missing, bool $published = false): array
|
|
{
|
|
$date = $input['reference_date'];
|
|
$context = ['operation' => $input['operation'], 'currency' => $input['currency']];
|
|
$exact = ($evaluation['status'] ?? null) === 'determinate'
|
|
? (string) BigRational::of($evaluation['result'])->toBigDecimal()
|
|
: null;
|
|
if ($exact === null && $missing === []) {
|
|
$missing = $evaluation['missing'] ?? ['eligible_parameter'];
|
|
}
|
|
$snapshot = [
|
|
'contract_version' => 1, 'scenario_kind' => $published ? 'fiscal_rule_published' : 'fiscal_rule_qa_preview',
|
|
'base' => $input['base'], 'currency' => $input['currency'], 'indicative_total' => $exact,
|
|
'legal_interpretation' => false, 'formula_version' => 'investmoz.tax.v1',
|
|
'context' => [
|
|
'reference_date' => $date, 'currency' => $input['currency'], 'currency_fraction_digits' => 2,
|
|
'scenario_id' => null, 'scenario_version' => 1, 'engine_version' => $published ? 'fiscal-published-v1' : 'fiscal-draft-preview-v1',
|
|
'ruleset_version' => $version['rule_code'].':'.$version['rule_version'],
|
|
],
|
|
'result' => [
|
|
'status' => $exact === null ? 'indeterminate' : 'calculated', 'value' => $exact, 'unit' => 'MZN',
|
|
'explanation' => $exact === null
|
|
? 'IVA indeterminado: o contexto, a fonte ou o período não permitem resolver o parâmetro deste lote QA.'
|
|
: 'IVA calculado com precisão decimal exacta, sem arredondamento. Ensaio QA de regra em rascunho; enquadramento declarado, não validado. Não é saldo de declaração nem valor a pagar.',
|
|
'missing_inputs' => $missing, 'source_ids' => [(string) $version['legal_source_id']],
|
|
],
|
|
'presentation' => ['value' => $exact, 'currency' => $input['currency'], 'rounding_applied' => false, 'purpose' => 'operation_tax_not_payment'],
|
|
// Exact rational steps supplement the decimal result; no float conversion.
|
|
'intermediate' => $evaluation,
|
|
'fiscal_provenance' => [
|
|
'mode' => $published ? 'published_version' : 'qa_draft_only', 'scope_status' => ($input['scope_declared'] ?? true) ? 'user_declared' : 'undetermined', 'context' => $context,
|
|
'rounding_policy' => $version['rounding_policy'], 'resolution' => $resolution,
|
|
'rule' => $version, 'source_acceptance' => 'Fonte oficial aceite pela decisão Tempo de 08/10/2026; não constitui aprovação jurídica desta operação ou publicação da regra.',
|
|
],
|
|
];
|
|
|
|
if ($published) {
|
|
$snapshot['result']['explanation'] = $exact === null
|
|
? 'IVA indeterminado: falta contexto, fonte ou parâmetro elegível para esta operação.'
|
|
: 'IVA calculado pela versão publicada identificada, sem arredondamento. Enquadramento declarado, não validado. Não é saldo de declaração nem valor a pagar.';
|
|
$snapshot['fiscal_provenance']['admitted_at'] = now()->toISOString();
|
|
$snapshot['fiscal_provenance']['source_acceptance'] = 'Fonte oficial aceite pela Tempo em 08/10/2026; não constitui validação jurídica desta operação.';
|
|
}
|
|
|
|
return $snapshot;
|
|
}
|
|
}
|