Integrate monthly IVA with projected sales in QA
This commit is contained in:
@@ -6,6 +6,7 @@ namespace App\Services;
|
||||
|
||||
use App\Models\InvestmentLegalSource;
|
||||
use App\Models\SimulationTaxRuleVersion;
|
||||
use Brick\Math\BigRational;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -35,8 +36,11 @@ final class SimulationPublishedFiscal
|
||||
->where('scope_key', 'mz.internal-general-net.mzn');
|
||||
}
|
||||
|
||||
public function admit(array $input): array
|
||||
public function admit(array $input, bool $missingBase = false): array
|
||||
{
|
||||
if (isset($input['monthly_sales'])) {
|
||||
return $this->admitMonthly($input);
|
||||
}
|
||||
// Called inside createPayload, after idempotent replay, never by the worker.
|
||||
abort_unless(DB::transactionLevel() > 0, 500);
|
||||
abort_unless(config('simulation-fiscal-consumer.enabled'), 503,
|
||||
@@ -63,6 +67,9 @@ final class SimulationPublishedFiscal
|
||||
$input['reference_date'], $input['reference_date'], ['currency' => $input['currency'], 'operation' => $input['operation']]);
|
||||
$rate = collect($resolution)->firstWhere('parameter_code', 'IVA_GENERAL_RATE');
|
||||
$missing = [];
|
||||
if ($missingBase) {
|
||||
$missing[] = 'taxable_sales';
|
||||
}
|
||||
$evaluation = null;
|
||||
if (! ($input['scope_declared'] ?? false)) {
|
||||
$missing[] = 'operation_scope';
|
||||
@@ -79,4 +86,51 @@ final class SimulationPublishedFiscal
|
||||
|
||||
return app(SimulationFiscalSnapshot::class)->build($version, $input, $resolution, $evaluation, $missing, true);
|
||||
}
|
||||
|
||||
private function admitMonthly(array $input): array
|
||||
{
|
||||
$rows = [];
|
||||
$baseTotal = BigRational::zero();
|
||||
$vatTotal = BigRational::zero();
|
||||
$complete = true;
|
||||
$previous = null;
|
||||
foreach ($input['monthly_sales'] as $sale) {
|
||||
abort_unless($previous === null || $sale['date'] === date('Y-m-d', strtotime($previous.' +1 month')), 422, 'A projecção deve conter meses consecutivos, sem duplicações.');
|
||||
$previous = $sale['date'];
|
||||
$known = $sale['amount'] !== null && $sale['amount'] !== '';
|
||||
$net = $input['sales_vat_basis'] === 'net';
|
||||
$month = $this->admit(['base' => $known && $net ? $sale['amount'] : null,
|
||||
'currency' => $input['currency'], 'reference_date' => $sale['date'],
|
||||
'operation' => 'internal_general_net', 'scope_declared' => $input['scope_declared']], ! $known || ! $net);
|
||||
$snapshot ??= $month;
|
||||
$rate = collect($month['fiscal_provenance']['resolution'])->firstWhere('parameter_code', 'IVA_GENERAL_RATE');
|
||||
$vat = $month['result']['value'];
|
||||
$status = ! $known ? 'missing_sales' : (! $net ? 'unsupported_basis' : ($vat === null ? 'indeterminate' : 'calculated'));
|
||||
$rows[] = ['date' => $sale['date'], 'sales_declared' => $sale['amount'],
|
||||
'net_sales' => $known && $net ? $sale['amount'] : null,
|
||||
'rate' => $vat !== null && ($rate['status'] ?? null) === 'resolved' ? $rate['value'] : null,
|
||||
'vat' => $vat, 'gross_sales' => $vat === null ? null : (string) BigRational::of($sale['amount'])->plus($vat)->toBigDecimal(),
|
||||
'status' => $status, 'rule_id' => $month['fiscal_provenance']['rule']['id'],
|
||||
'rule_version' => $month['fiscal_provenance']['rule']['rule_version']];
|
||||
if ($vat === null) {
|
||||
$complete = false;
|
||||
} else {
|
||||
$baseTotal = $baseTotal->plus($sale['amount']);
|
||||
$vatTotal = $vatTotal->plus($vat);
|
||||
}
|
||||
}
|
||||
$value = $complete ? (string) $vatTotal->toBigDecimal() : null;
|
||||
$snapshot['base'] = $complete ? (string) $baseTotal->toBigDecimal() : null;
|
||||
$snapshot['indicative_total'] = $value;
|
||||
$snapshot['result']['value'] = $value;
|
||||
$snapshot['result']['status'] = $complete ? 'calculated' : 'indeterminate';
|
||||
$snapshot['result']['missing_inputs'] = $complete ? [] : ['monthly_sales_or_net_basis_or_scope'];
|
||||
$snapshot['result']['explanation'] = 'IVA mensal sobre vendas declaradas sem IVA, pela versão publicada congelada na admissão. Valores com IVA incluído ou sem informação permanecem indeterminados. Não é imposto final a pagar.';
|
||||
$snapshot['presentation']['value'] = $value;
|
||||
$snapshot['intermediate'] = null;
|
||||
$snapshot['monthly_projection'] = ['input' => $input, 'rows' => $rows,
|
||||
'cash_treatment' => 'Informação separada da tesouraria: os recebimentos declarados não são aumentados pelo IVA nem o IVA é deduzido como custo ou imposto a pagar. Calendário de cobrança e liquidação fiscal não é inferido.'];
|
||||
|
||||
return $snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user