boundRule()->where('status', 'published')->exists(); return ['enabled' => $eligible, 'coverage_start' => '2026-01-01', 'coverage_end' => '2026-12-31', 'message' => $eligible ? 'IVA geral sobre base líquida disponível; enquadramento declarado.' : 'O cálculo de IVA geral sobre base líquida está indisponível para novas execuções. Os históricos mantêm-se acessíveis.']; } private function boundRule(): Builder { if (! Str::isUuid((string) config('simulation-fiscal-consumer.rule_id')) || config('simulation-fiscal-consumer.rule_version') < 1) { return SimulationTaxRuleVersion::query()->whereRaw('false'); } return SimulationTaxRuleVersion::query()->whereKey(config('simulation-fiscal-consumer.rule_id')) ->where('rule_version', config('simulation-fiscal-consumer.rule_version')) ->where('rule_code', 'IVA-GERAL-BASE-LIQUIDA')->where('component', 'IVA') ->where('scope_key', 'mz.internal-general-net.mzn'); } public function admit(array $input): array { // Called inside createPayload, after idempotent replay, never by the worker. abort_unless(DB::transactionLevel() > 0, 500); abort_unless(config('simulation-fiscal-consumer.enabled'), 503, 'O cálculo de IVA está temporariamente indisponível. Os dados e históricos foram preservados.'); DB::select('select pg_advisory_xact_lock_shared(261021, hashtext(?))', [(string) config('simulation-fiscal-consumer.rule_id')]); $rule = $this->boundRule()->first(); abort_unless($rule && $rule->status === 'published', 503, 'A versão autorizada de IVA não está disponível para novas execuções. Os históricos foram preservados.'); abort_if($input['reference_date'] < '2026-01-01' || $input['reference_date'] > '2026-12-31', 422, 'Este cálculo abrange apenas exigibilidade em 2026. As entradas foram preservadas.'); abort_if(collect($rule->rule_definition['nodes'] ?? [])->contains(fn (array $node): bool => ($node['op'] ?? null) === 'round'), 422, 'A versão seleccionada não é compatível com o cálculo exacto deste consumidor.'); DB::select('select pg_advisory_xact_lock_shared(261022, hashtext(?))', [(string) $rule->legal_source_id]); $source = InvestmentLegalSource::whereKey($rule->legal_source_id)->firstOrFail(); // Publish calculation provenance, not private governance notes or staff identifiers. $version = array_intersect_key($rule->attributesToArray(), array_flip([ 'id', 'rule_code', 'rule_version', 'component', 'scope_key', 'status', 'valid_from', 'valid_until', 'legal_source_id', 'source_version_no', 'source_sha256', 'rule_definition', 'parameters', 'rounding_policy', ])); $version['source'] = array_intersect_key($source->attributesToArray(), array_flip([ 'id', 'title', 'url', 'diploma', 'article', 'competent_entity', 'valid_from', 'valid_until', 'validation_status', 'version_no', ])); $resolution = app(SimulationTaxParameterResolver::class)->resolvePublishedForPeriod('IVA', $input['reference_date'], $input['reference_date'], ['currency' => $input['currency'], 'operation' => $input['operation']]); $rate = collect($resolution)->firstWhere('parameter_code', 'IVA_GENERAL_RATE'); $missing = []; $evaluation = null; if (! ($input['scope_declared'] ?? false)) { $missing[] = 'operation_scope'; } if (($rate['status'] ?? null) !== 'resolved' || ($rate['unit'] ?? null) !== 'percent' || ($rate['rule_id'] ?? null) !== (string) $rule->id || (int) ($rate['rule_version'] ?? 0) !== (int) $rule->rule_version) { $missing[] = 'eligible_parameter'; } if ($missing === []) { $evaluation = app(SimulationTaxRuleExpression::class)->evaluate($rule->rule_definition, ['base_tributavel' => $input['base']], ['iva_general_rate' => $rate['value']]); } return app(SimulationFiscalSnapshot::class)->build($version, $input, $resolution, $evaluation, $missing, true); } }