60 lines
5.0 KiB
PHP
60 lines
5.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
/** Explains a failed selection; never changes answers, eligibility or calculation. */
|
|
final class SimulationIvaDiagnostics
|
|
{
|
|
/**
|
|
* @param array<array-key, mixed> $context
|
|
* @param array<array-key, mixed> $versions
|
|
* @return array<array-key, mixed>
|
|
*/
|
|
public function explain(array $versions, string $start, string $end, array $context): array
|
|
{
|
|
$diagnostics = [];
|
|
foreach ($versions as $version) {
|
|
$parameter = $version['parameters']['IVA_GENERAL_RATE'] ?? null;
|
|
if (! is_array($parameter)) {
|
|
continue;
|
|
}
|
|
$issues = [];
|
|
$add = function (string $category, ?string $field, string $label, mixed $received, string $expected, string $message) use (&$issues): void {
|
|
$issues[] = compact('category', 'field', 'label', 'received', 'expected', 'message');
|
|
};
|
|
if ($start < $version['valid_from'] || ($version['valid_until'] !== null && $end > $version['valid_until'])) {
|
|
$add('period_unavailable', 'fiscal_period', 'Período', "$start a $end", $version['valid_from'].' a '.($version['valid_until'] ?? 'sem data final indicada'), 'Esta versão da regra não abrange todo o período seleccionado. Não altere a data real da operação para obter um resultado.');
|
|
}
|
|
foreach ($parameter['conditions'] ?? [] as $key => $expected) {
|
|
$received = $context[$key] ?? null;
|
|
if ($received === $expected) {
|
|
continue;
|
|
}
|
|
if ($key === 'currency') {
|
|
$category = $received === null || $received === '' ? 'missing_field' : (preg_match('/^[A-Z]{3}$/D', $received) ? 'out_of_scope' : 'invalid_value');
|
|
$add($category, 'fiscal_currency', 'Moeda', $received, $expected, $category === 'missing_field' ? 'Indique a moeda da operação.' : 'Esta versão aceita apenas '.$expected.'. Reveja a moeda ou utilize um cálculo adequado à operação; a resposta não foi alterada.');
|
|
} elseif ($key === 'operation' && ! array_key_exists('operation', $context) && $expected === 'internal_general_net' && in_array($context['fiscal_operation'] ?? null, ['import', 'export', 'non_resident', 'refund'], true)) {
|
|
$add('out_of_scope', 'fiscal_operation', 'Operação', $context['fiscal_operation'], 'Operação interna à taxa geral, sobre base líquida já apurada', 'A operação declarada está excluída desta versão. Utilize um cálculo adequado à operação; não altere a resposta para obter um resultado.');
|
|
} elseif ($key === 'operation' && ! array_key_exists('operation', $context)) {
|
|
$add('system_configuration', 'fiscal_operation', 'Operação', $context['fiscal_operation'] ?? null, $expected === 'internal_general_net' ? 'Operação interna à taxa geral, sobre base líquida já apurada' : $expected, 'Limitação de integração do sistema: esta consulta não comunica o enquadramento específico exigido pela versão. A resposta genérica não permite inferi-lo. Utilize o formulário IVA — taxa geral, com declaração explícita do âmbito; não altere respostas para forçar compatibilidade.');
|
|
} elseif ($key === 'operation') {
|
|
$add($received === null || $received === '' ? 'missing_field' : 'out_of_scope', 'fiscal_operation', 'Operação', $received, $expected === 'internal_general_net' ? 'Operação interna à taxa geral, sobre base líquida já apurada' : $expected, 'A operação não está abrangida por esta versão; utilize um cálculo adequado à operação declarada.');
|
|
} else {
|
|
$add('system_configuration', null, 'Configuração da regra', null, 'Condições publicadas ligadas a campos deste formulário', 'O sistema não consegue relacionar todas as condições desta versão com o formulário. Não é uma falha das suas respostas.');
|
|
}
|
|
}
|
|
if (! SimulationFiscalSourceAcceptance::eligible($version['source'] ?? [], $version['source_sha256'] ?? null)
|
|
|| ($version['source_version_no'] ?? null) !== ($version['source']['version_no'] ?? null)
|
|
|| ($version['rule_definition']['language'] ?? null) !== 'investmoz.tax.v1') {
|
|
$add('system_configuration', null, 'Regra', null, 'Versão publicada com fonte e configuração coerentes', 'A configuração ou a fonte da regra não permite resolver este parâmetro. Não altere as respostas; é necessária correcção do sistema.');
|
|
}
|
|
if ($issues !== []) {
|
|
$source = array_intersect_key($version['source'] ?? [], array_flip(['title', 'diploma', 'article', 'url']));
|
|
$diagnostics[] = ['label' => 'IVA — taxa geral', 'rule_version' => $version['rule_version'], 'validity' => ['start' => $version['valid_from'], 'end' => $version['valid_until']], 'source' => $source, 'issues' => $issues];
|
|
}
|
|
}
|
|
|
|
return $diagnostics;
|
|
}
|
|
}
|