Skip to content

Commit 360fdf4

Browse files
authored
Merge pull request #92 from LibreCodeCoop/fix/csll-retencao-fallback
fix: fallback tpRetPisCofins when CSLL retention is zero
2 parents a6abb5e + a45fb8e commit 360fdf4

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

Http/Controllers/InvoiceController.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,14 @@ protected function federalPayloadValues(float $invoiceAmount): array
11041104
{
11051105
$situacaoTributaria = $this->normalizedFederalSelectValue(setting('nfse.federal_piscofins_situacao_tributaria', ''));
11061106
$tipoRetencao = $this->normalizedFederalSelectValue(setting('nfse.federal_piscofins_tipo_retencao', ''));
1107+
$valorCsllRetencao = $this->calculateFederalRetentionValue($invoiceAmount, 'federal_valor_csll');
1108+
1109+
if (in_array($tipoRetencao, ['4', '5', '6'], true) && $valorCsllRetencao === '') {
1110+
// Gateway currently rejects tpRetPisCofins != 0 without vRetCSLL.
1111+
// When configured CSLL retention is zero, fallback avoids invalid payloads.
1112+
$tipoRetencao = '0';
1113+
}
1114+
11071115
$isSimplesNacionalOptant = $this->normalizedOpcaoSimplesNacional() === 2;
11081116

11091117
$totalTributosPercentualFederal = $this->normalizedFederalDecimal(setting($isSimplesNacionalOptant ? 'nfse.tributos_fed_sn' : 'nfse.tributos_fed_p', ''));
@@ -1160,7 +1168,7 @@ protected function federalPayloadValues(float $invoiceAmount): array
11601168
: '',
11611169
'federalValorIrrf' => $this->calculateFederalRetentionValue($invoiceAmount, 'federal_valor_irrf'),
11621170
'federalValorCsll' => $tipoRetencao !== '0'
1163-
? $this->calculateFederalRetentionValue($invoiceAmount, 'federal_valor_csll')
1171+
? $valorCsllRetencao
11641172
: '',
11651173
// Produção restrita currently rejects vRetCP (RNG6110), so keep CP as UI/config only.
11661174
'federalValorCp' => '',

tests/Unit/Http/Controllers/InvoiceControllerTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,66 @@ public function testRuntimeXmlBuilderStartsInfDpsWithTpAmbBeforeMunicipalityFiel
529529
self::assertStringNotContainsString('<cMun>3303302</cMun>', $normalizedXml);
530530
}
531531

532+
public function testEmitFallsBackToNoRetentionWhenTypeRequiresCsllButConfiguredValueIsZero(): void
533+
{
534+
ControllerIsolationState::$settings['nfse.federal_piscofins_tipo_retencao'] = '4';
535+
ControllerIsolationState::$settings['nfse.federal_valor_csll'] = '0.00';
536+
537+
$invoice = InvoiceControllerIsolationState::makeInvoice(
538+
id: 204,
539+
amount: 1000.00,
540+
items: [
541+
['name' => 'Servico fallback retencao'],
542+
],
543+
);
544+
545+
$client = new class () implements NfseClientInterface {
546+
public ?DpsData $capturedDps = null;
547+
548+
public function emit(DpsData $dps): ReceiptData
549+
{
550+
$this->capturedDps = $dps;
551+
552+
return new ReceiptData(
553+
nfseNumber: 'NF-204',
554+
chaveAcesso: 'CHAVE-204',
555+
dataEmissao: '2026-04-03T12:00:00-03:00',
556+
);
557+
}
558+
559+
public function query(string $chaveAcesso): ReceiptData
560+
{
561+
throw new \BadMethodCallException('Not used in this test.');
562+
}
563+
564+
public function cancel(string $chaveAcesso, string $motivo): bool
565+
{
566+
throw new \BadMethodCallException('Not used in this test.');
567+
}
568+
};
569+
570+
$controller = new class ($client) extends InvoiceController {
571+
public function __construct(private readonly NfseClientInterface $client)
572+
{
573+
}
574+
575+
protected function makeClient(bool $sandboxMode): NfseClientInterface
576+
{
577+
return $this->client;
578+
}
579+
580+
protected function hasCertificateSecret(string $cnpj): bool
581+
{
582+
return true;
583+
}
584+
};
585+
586+
$controller->emit($invoice);
587+
588+
self::assertSame('0', $client->capturedDps?->federalPiscofinsTipoRetencao);
589+
self::assertSame('', $client->capturedDps?->federalValorCsll);
590+
}
591+
532592
public function testEmitPrefersDefaultCompanyServiceOverLegacyFiscalSettings(): void
533593
{
534594
$invoice = InvoiceControllerIsolationState::makeInvoice(

0 commit comments

Comments
 (0)