diff --git a/src/Danfse/DanfseTemplate.php b/src/Danfse/DanfseTemplate.php index d3f49bd..b9e42e6 100644 --- a/src/Danfse/DanfseTemplate.php +++ b/src/Danfse/DanfseTemplate.php @@ -150,7 +150,13 @@ public function buildData(array $nfse): array 'servico' => [ 'codigo_trib_nacional' => $this->formatter->codTribNacional($this->val($cServ, 'cTribNac')), - 'desc_trib_nacional' => $this->formatter->limit(trim($this->val($infNfse, 'xTribNac')), 60), + // NT008 2.4.5 prefers an authorized municipal description + // over the national one. The length is suggested, not a new + // tax-code validation or data mutation. + 'desc_trib_nacional' => $this->formatter->limit( + $this->val($infNfse, 'xTribMun') ?: $this->val($infNfse, 'xTribNac'), + 167, + ), 'codigo_trib_municipal' => $this->val($cServ, 'cTribMun') ?: '-', 'codigo_nbs' => $this->formattedNbs($this->val($cServ, 'cNBS')), 'desc_trib_municipal' => $this->formatter->limit(trim($this->val($infNfse, 'xTribMun')), 60), @@ -179,6 +185,11 @@ public function buildData(array $nfse): array ], 'tributacao_federal' => [ + // NT008 note 6: optional PIS/COFINS line is present only + // for actual issue competence through calendar year 2026. + 'mostrar_linha_2026' => $this->showFederalDetailsForCompetence( + $this->val($infDps, 'dCompet'), + ), 'irrf' => $this->currencyOrDash($this->val($tribFed, 'vRetIRRF')), 'cp' => $this->currencyOrDash($this->val($tribFed, 'vRetCP')), 'csll' => $this->currencyOrDash($this->val($tribFed, 'vRetCSLL')), @@ -417,6 +428,17 @@ private function purposeLabel(string $value): string }; } + private function showFederalDetailsForCompetence(string $competence): bool + { + // Do not use today's date: printing an older authorized invoice + // must reproduce the display rules for its original competence. + if (preg_match('/^(\\d{4})-\\d{2}-\\d{2}$/D', $competence, $matches) !== 1) { + return false; + } + + return (int) $matches[1] <= 2026; + } + private function pisCofinsRetentionLabel(string $value): string { return match ($value) { diff --git a/src/Danfse/HTMLTemplate.php b/src/Danfse/HTMLTemplate.php index 266ef91..0383ad0 100644 --- a/src/Danfse/HTMLTemplate.php +++ b/src/Danfse/HTMLTemplate.php @@ -366,11 +366,13 @@ Contribuição Previdenciária - Retida Contribuições Sociais - Retidas - + + PIS - Débito Apuração Própria COFINS - Débito Apuração Própria Tipo de retenção PIS/COFINS/CSLL + diff --git a/tests/Unit/Danfse/DanfseGoldenReferenceTest.php b/tests/Unit/Danfse/DanfseGoldenReferenceTest.php index bfabaac..2c485ab 100644 --- a/tests/Unit/Danfse/DanfseGoldenReferenceTest.php +++ b/tests/Unit/Danfse/DanfseGoldenReferenceTest.php @@ -104,7 +104,7 @@ public function testLongOfficialDescriptionsUseStableSixtyCharacterSummary(): vo $data = (new DanfseTemplate())->buildData($nfse); - self::assertSame(63, mb_strlen($data['servico']['desc_trib_nacional'])); + self::assertSame(170, mb_strlen($data['servico']['desc_trib_nacional'])); self::assertSame(63, mb_strlen($data['servico']['desc_trib_municipal'])); self::assertStringEndsWith('...', $data['servico']['desc_trib_nacional']); self::assertStringEndsWith('...', $data['servico']['desc_trib_municipal']); diff --git a/tests/Unit/Danfse/DanfseTemplateTest.php b/tests/Unit/Danfse/DanfseTemplateTest.php index f0dfabe..d0666cc 100644 --- a/tests/Unit/Danfse/DanfseTemplateTest.php +++ b/tests/Unit/Danfse/DanfseTemplateTest.php @@ -135,6 +135,40 @@ public function testAuthorizedMunicipalTotalsUseNfseValuesNotDpsTaxFlags(): void self::assertSame('R$ 630,00', $data['tributacao_municipal']['issqn_apurado']); } + public function testMunicipalTaxDescriptionWinsButNationalIsFallback(): void + { + $nfse = $this->fixtureNfseData(); + $nfse['infNFSe']['xTribNac'] = 'Descricao nacional sintetica'; + $nfse['infNFSe']['xTribMun'] = 'Descricao municipal sintetica'; + + $template = new DanfseTemplate(); + self::assertSame('Descricao municipal sintetica', $template->buildData($nfse)['servico']['desc_trib_nacional']); + self::assertStringContainsString('Descricao municipal sintetica', $template->render($nfse, new DanfseConfig())); + self::assertStringNotContainsString('Descricao nacional sintetica', $template->render($nfse, new DanfseConfig())); + + unset($nfse['infNFSe']['xTribMun']); + self::assertSame('Descricao nacional sintetica', $template->buildData($nfse)['servico']['desc_trib_nacional']); + } + + public function testFederalDetailRowFollowsOriginalFiscalCompetence(): void + { + $nfse = $this->fixtureNfseData(); + $template = new DanfseTemplate(); + + $nfse['infNFSe']['DPS']['infDPS']['dCompet'] = '2026-12-31'; + self::assertTrue($template->buildData($nfse)['tributacao_federal']['mostrar_linha_2026']); + self::assertStringContainsString('class="federal-competence-2026"', $template->render($nfse, new DanfseConfig())); + + $nfse['infNFSe']['DPS']['infDPS']['dCompet'] = '2027-01-01'; + self::assertFalse($template->buildData($nfse)['tributacao_federal']['mostrar_linha_2026']); + $html = $template->render($nfse, new DanfseConfig()); + self::assertStringNotContainsString('class="federal-competence-2026"', $html); + self::assertStringContainsString('Contribuições Sociais - Retidas', $html); + + unset($nfse['infNFSe']['DPS']['infDPS']['dCompet']); + self::assertFalse($template->buildData($nfse)['tributacao_federal']['mostrar_linha_2026']); + } + public function testDescriptionPreservesNewlinesWithoutRenderingMarkup(): void { $nfse = $this->fixtureNfseData();