Pular para conteúdo

Geração de NFS-e — TX2 / JSON — Mapeamento Profundo

Objetivo

Documentação rastreável, campo a campo, da geração de NFS-e com dois formatos (TX2 v1 e JSON v2), incluindo cadeia de determinação dos valores de ISS e retenções.


Método Principal

Diferença da NF-e: A NFS-e não tem um método _gerar_nfse_tx2() separado. A montagem está embutida inline no fluxo de geração dentro de account.py (linhas 4450-5062).

Método Linha Descrição
Inline no fluxo NFS-e 4450-5062 Monta invoice_vals, invoice_emit_vals e serializa
_gerar_nfse_tx2_hook(invoice_vals, invoice_emit_vals) 5007 Hook para customização
_get_json_plugnotas(invoice_vals, invoice_emit_vals) 4482 Converte para JSON PlugNotas (v2)

Integrador

Integrador Configuração Formato
v1 (padrão) l10n_br_documento_id.l10n_br_integrador = '1' (ou vazio) TX2 (INCLUIR...campo%3Dvalor...SALVAR)
v2 (PlugNotas) l10n_br_documento_id.l10n_br_integrador = '2' JSON via POST /api/v1/nfse

Onde configurar: Operação Fiscal → Documento Fiscal → campo "Integrador"


Pré-requisitos e Validações

Validação Condição Erro
Múltiplos itens Fatura com > 1 linha produto E município não suporta multi-item E parâmetro unificar_item_nfse ≠ 1 "Nota Fiscal de Serviço não pode ter mais de 1 item"
Sequência RPS l10n_br_numero_nfe_id não configurado no documento fiscal "Operação Fiscal não informada"

Municípios que aceitam múltiplos itens sem unificação

3509502 (Campinas), 4211900 (Palhoça), 4209003 (Joinville), 4205407 (Florianópolis)


Parâmetros de Sistema

Parâmetro Padrão Cadeia de Efeito
unificar_item_nfse 0 Se 1: agrega todas as linhas em item único (usa l10n_br_descricao_servico do cabeçalho). Exceção: se integrador v2, sempre desligado
add_infoadicional_nfse 0 Se 1: concatena invoice_line.l10n_br_informacao_adicional na discriminação do serviço

BLOCO RPS — Numeração e Datas

Campo TX2 Campo JSON (v2) Cadeia de Origem Como Alterar
SituacaoNota 🔒 Fixo 1 (nota normal) ❌ Fixo
TipoRps rps.tipo 🔒 Fixo 1 (RPS provisório) ❌ Fixo
SerieRps rps.serie Fatura.l10n_br_serie_nf → fallback: Documento Fiscal.l10n_br_serie_nfe ✅ Fatura → Série ou Documentos Fiscais → Série
NumeroRps rps.numero Se vazio: Documento Fiscal.l10n_br_numero_nfe_id.next_by_id() ✅ Sequência em Documentos Fiscais
DataEmissao rps.dataEmissao datetime.now(tz='America/Sao_Paulo')Exceção Manaus: trunca só data ❌ Horário atual
Competencia rps.competencia Data da emissão (formato YYYY-MM-DD) ❌ Automático
InformacoesComplementares informacoesComplementares Fatura.l10n_br_informacao_complementar — formatado por _format_obs() ✅ Fatura → Informação Complementar

NFS-e Substituta

Condição Campos TX2 Origem
Fatura.l10n_br_nfse_substituta = True NumeroNfseSubstituida, NumeroRpsSubstituido, SerieRpsSubstituido, DataEmissaoNfseSubstituida, TipoRpsSubstituido (fixo 1) ✅ Fatura → campos de substituição

BLOCO PRESTADOR — Empresa Emitente

Campo TX2 Campo JSON (v2) Cadeia de Origem Como Alterar
CpfCnpjPrestador prestador.cpfCnpj company_id.l10n_br_cnpj (sem formatação) ✅ Empresa → CNPJ
InscricaoMunicipalPrestador prestador.inscricaoMunicipal company_id.l10n_br_im ✅ Empresa → IM. No v2: pode ser removido se l10n_br_nfse_nacional_prestador_im ≠ True
RazaoSocialPrestador prestador.razaoSocial company_id.l10n_br_razao_social → fallback: company_id.name ✅ Empresa → Razão Social
EnderecoPrestador prestador.endereco.logradouro company_id.street ✅ Empresa → Endereço
NumeroPrestador prestador.endereco.numero company_id.l10n_br_endereco_numero ✅ Empresa → Número
BairroPrestador prestador.endereco.bairro company_id.l10n_br_endereco_bairro (máx 60) ✅ Empresa → Bairro
CodigoCidadePrestador prestador.endereco.codigoCidade company_id.l10n_br_municipio_id.codigo_ibge ✅ Empresa → Município
UfPrestador prestador.endereco.estado company_id.state_id.code ✅ Empresa → Estado
CepPrestador prestador.endereco.cep company_id.zip sem formatação ✅ Empresa → CEP
EmailPrestador prestador.email company_id.email ✅ Empresa → E-mail
TelefonePrestador company_id.phone (somente dígitos) ✅ Empresa → Telefone
OptanteSimplesNacional prestador.simplesNacional company_id.l10n_br_regime_tributario in ['1','2','4']1, senão → 2 ✅ Empresa → Regime Tributário
RegimeEspecialTributacao company_id.l10n_br_regime_especial_tributacao ✅ Empresa → Regime Especial Tributação
IncentivadorCultural 🔒 Fixo 2 (não é incentivador) ❌ Fixo
IncentivoFiscal 🔒 Fixo 2 (sem incentivo) ❌ Fixo
TipoTributacao 🔒 Default 6. Sobrescrito se ISS exigibilidade 24. Sobrescrito se exterior São Paulo → 6. Sobrescrito se l10n_br_iss_municipio_id preenchido → 7 Parcial — depende da situação

BLOCO TOMADOR — Parceiro/Cliente

Campo TX2 Campo JSON (v2) Cadeia de Origem Regra Especial
CpfCnpjTomador tomador.cpfCnpj partner_id.l10n_br_cnpj ou l10n_br_cpf. Se exterior (SP): fixo 99999999999 ✅ Contatos → CNPJ/CPF
RazaoSocialTomador tomador.razaoSocial partner_id.l10n_br_razao_social → fallback: name. Municípios Palhoça/Joinville: formatação especial ✅ Contatos → Razão Social
InscricaoMunicipalTomador tomador.inscricaoMunicipal partner_id.l10n_br_im ✅ Contatos → IM
InscricaoEstadualTomador partner_id.l10n_br_ie ✅ Contatos → IE
EnderecoTomador tomador.endereco.logradouro partner_id.street ✅ Contatos → Endereço
CodigoCidadeTomador tomador.endereco.codigoCidade partner_id.l10n_br_municipio_id.codigo_ibge. Se exterior (BH, SJC, Rio Claro): 9999999 ou 99999 ✅ Contatos → Município
UfTomador tomador.endereco.estado partner_id.state_id.code. Se exterior: EX (municípios específicos) ✅ Contatos → Estado
PaisTomador Varia por município: country.code, country.name, country.l10n_br_codigo_bacen, ou fixo 1058 ⚠️ Ver tabela de variações
EmailTomador tomador.email partner_id.email ✅ Contatos → E-mail

BLOCO SERVIÇO — Dados do Serviço

Código de Serviço

Campo TX2 Cadeia de Origem Prioridade/Regra
CodigoItemListaServico invoice_line.product_id.l10n_br_codigo_servico ✅ Produto → "Código do Serviço" (obrigatório). Exceção Florianópolis: campo é esvaziado
CodigoTributacaoMunicipio invoice_line.product_id.l10n_br_codigo_tributacao_servico ✅ Produto → "Código Tributação Serviço". Exceções Campinas, Brasília, Florianópolis: campo é esvaziado
CodigoNBS invoice_line.product_id.l10n_br_codigo_nbs ✅ Produto → "Código NBS"
CodigoCnae Cadeia de prioridade por município: Ver tabela abaixo ✅ Empresa → CNAE ou Produto → campos
CodigoOperacao invoice_line.product_id.l10n_br_codigo_operacao ✅ Produto → "Indicador Operação IBS/CBS" (condicional: só se preenchido)
ClassificacaoTributariaIbsCbs invoice_line.product_id.l10n_br_classtrib_ibs_cbs ✅ Produto → "Classificação Tributária IBS/CBS" (condicional: só se preenchido)
SituacaoTributariaIbsCbs invoice_line.l10n_br_ibscbs_cst 📋 Linha de fatura → CST IBS/CBS (condicional: só se preenchido)
ClassifTributariaRegularIbsCbs invoice_line.product_id.l10n_br_classtrib_ibs_cbs ✅ Produto → "Class. Tributária IBS/CBS" — Somente se ibscbs_cst ≠ '000' (suspensão ou benefício)

Reforma Tributária (IBS/CBS): Os campos SituacaoTributariaIbsCbs e ClassifTributariaRegularIbsCbs foram adicionados em 06/04/2026 (commit f2fe26d3). São condicionais — somente gerados se os campos de origem estiverem preenchidos.

Cadeia de prioridade do CNAE por município

Município (IBGE) Fonte do CodigoCnae Regra
Padrão company_id.l10n_br_cnae (truncado 7 chars) CNAE da empresa
Londrina (4115200) / Barueri (3505708) company_id.l10n_br_cnae (completo) CNAE sem truncar
Barueri (3505708) product.l10n_br_codigo_servico Código de serviço do produto
São José dos Campos (3549904) product.l10n_br_codigo_tributacao_servico → fallback: company.l10n_br_cnae Código tributação do produto
Campinas (3509502) / Florianópolis (4205407) product.l10n_br_codigo_tributacao_servico → fallback: company.l10n_br_cnae Idem SJC
Brasília (5300108) product.l10n_br_codigo_tributacao_servico → fallback: company.l10n_br_cnae Idem

Discriminação do Serviço

Campo TX2 Cadeia de Origem Regras
DiscriminacaoServico invoice_line.name + (opcionalmente) invoice_line.l10n_br_informacao_adicional Se unificado: usa invoice.l10n_br_descricao_servico. Municípios Londrina/Barueri: URL encoding via urllib.parse.quote()

ISS — Alíquota e Valor

Campo TX2 Cadeia de Origem Completa Como Alterar
AliquotaISS invoice_line.l10n_br_iss_aliquota → fallback: l10n_br_iss_ret_aliquota. Se unificado: max() de todas as linhas ✅ Campo da linha, preenchido pelo motor fiscal
ValorIss sum(invoice_line_ids.mapped('l10n_br_iss_valor')). Exceção Marília (3530607): fixo 0.00. Exceção Florianópolis (4205407): recalculado por alíquota 🧮 Calculado
IssRetido 1 se iss_ret_valor > 0, senão 2 🧮 Automático baseado nas retenções
ValorIssRetido sum(l10n_br_iss_ret_valor) ou valor da linha 🧮 Calculado pelo motor fiscal
ExigibilidadeISS invoice_line.product_id.l10n_br_exigibilidade_iss (default 1). Se exterior sem ISS: 4 (exportação) ✅ Produto → "Exigibilidade ISS"

Cadeia de determinação da alíquota ISS no motor fiscal:

Operação Fiscal.l10n_br_iss_aliquota (se > 0)
  → values_to_update['l10n_br_iss_aliquota'] = operação.alíquota
  → values_to_update['l10n_br_iss_valor'] = base × alíquota / 100
Se operação sem ISS → Fica False
Origem: sale_order.py linha 1735 / account.py linha 10789 Onde configurar: ✅ Operação Fiscal → "Alíquota ISS (%)"

Retenções Federais

Campo TX2 Campo JSON (v2) Cadeia de Origem Como Alterar
AliquotaPIS / ValorPIS retencao.pis.aliquota/valor invoice_line.l10n_br_pis_ret_aliquota / sum(l10n_br_pis_ret_valor) ✅ Motor fiscal → Operação Fiscal → retenção PIS
AliquotaCOFINS / ValorCOFINS retencao.cofins.aliquota/valor invoice_line.l10n_br_cofins_ret_aliquota / sum(l10n_br_cofins_ret_valor) ✅ Motor fiscal → Operação Fiscal → retenção COFINS
AliquotaCSLL / ValorCSLL retencao.csll.aliquota/valor invoice_line.l10n_br_csll_ret_aliquota / sum(l10n_br_csll_ret_valor) ✅ Motor fiscal → Operação Fiscal → retenção CSLL
AliquotaIR / ValorIR retencao.irrf.aliquota/valor invoice_line.l10n_br_irpj_ret_aliquota / sum(l10n_br_irpj_ret_valor) ✅ Motor fiscal → Operação Fiscal → retenção IRPJ
AliquotaINSS / ValorINSS retencao.cpp.aliquota/valor invoice_line.l10n_br_inss_ret_aliquota / sum(l10n_br_inss_ret_valor) ✅ Motor fiscal → Operação Fiscal → retenção INSS

Regra JSON v2 — tipoRetencaoPisCofinsCSLL: Determinado automaticamente no código linha 4450-4468 por combinação de PIS+COFINS+CSLL retidos (0=nenhum, 3=todos, 4=PIS+COFINS, etc.)

Fallback PIS/COFINS normal: Se ValorPIS/ValorCOFINS retido = 0, o JSON v2 substitui pela alíquota/valor normal (não retido) — linhas 4470-4476.

Valores Totais

Campo TX2 Cadeia de Origem Regra
ValorServicos Normal: invoice_line.l10n_br_total_nfe. Unificado: sum(all_lines.l10n_br_total_nfe) 🧮 Calculado
BaseCalculo Normalmente = ValorServicos. Exceção: se material aplicado ao serviço → subtrai valor do material 🧮 Calculado
ValorDeducoes invoice_line.l10n_br_iss_deducao + material aplicado. Barueri: = total retido ✅ Linha → Dedução ISS
ValorLiquidoNfse sum(l10n_br_total_nfe) - total_retido 🧮 Calculado

Configurações da Empresa Específicas para NFS-e

Campo Empresa Efeito na Geração Como Alterar
l10n_br_show_infofisco_nfse Se True: inclui l10n_br_informacao_fiscal como OutrasInformacoes / DESCRICAORPS ✅ Empresa → "Mostrar Info Fiscal NFS-e"
l10n_br_show_infocomplementar_nfse Se True: inclui l10n_br_informacao_complementar como OutrasInformacoes ✅ Empresa → "Mostrar Info Complementar NFS-e"
l10n_br_municipio_id Determina variações de layout — cada prefeitura tem regras específicas de campos ✅ Empresa → Município
l10n_br_im IM do prestador — obrigatório para maioria dos municípios ✅ Empresa → IM
l10n_br_cnae CNAE da empresa — usado como fallback em CodigoCnae ✅ Empresa → CNAE
l10n_br_regime_especial_tributacao Código do regime especial (MEI, EIRELI, etc.) ✅ Empresa → Regime Especial

Configurações do Produto Específicas para NFS-e

Campo Produto Efeito TX2 Onde Configurar
l10n_br_codigo_servico CodigoItemListaServicoobrigatório ✅ Produtos → "Código do Serviço"
l10n_br_codigo_tributacao_servico CodigoTributacaoMunicipio + CodigoCnae (municípios específicos) ✅ Produtos → "Código Tributação Serviço"
l10n_br_codigo_nbs CodigoNBS ✅ Produtos → "Código NBS"
l10n_br_exigibilidade_iss ExigibilidadeISS (default 1=exigível) ✅ Produtos → "Exigibilidade ISS"
l10n_br_natureza_iss NaturezaTributacao (somente Rio Claro / SJC) ✅ Produtos → "Natureza ISS"
l10n_br_infendobraimovel Determina se inclui dados de imóvel/obra. Opções: obra, imovel, ambos, nao ✅ Produtos → "Informar Endereço da Obra/Imovel"
l10n_br_codigo_operacao CodigoOperacao (reforma tributária IBS/CBS) ✅ Produtos → "Código Operação"
l10n_br_classtrib_ibs_cbs ClassificacaoTributariaIbsCbs + ClassifTributariaRegularIbsCbs (reforma tributária) ✅ Produtos → "Class. Tributária IBS/CBS"
l10n_br_material_aplicado_servico Se True: valor do produto é subtraído da base ISS como material aplicado ✅ Produtos → "Material Aplicado ao Serviço"

Variações por Município — Tabela Consolidada

IBGE Município Variações no Código Impacto
3550308 São Paulo Exterior: TipoTributacao=6, Tributavel=N, PaisTomador=nome, MunicipioIncidencia=9999999 Layout exterior
3505708 Barueri URL encoding discriminação, CodigoCnae=codigo_servico, CodigoCidadePrestacao sufixo _2 Layout especial
4211900 Palhoça/SC _format_obs_4211900() para razão social, multi-itens, AliquotaServico extra Formatação diferente
4209003 Joinville/SC Mesmo que Palhoça Idem
4205407 Florianópolis AliquotaServico extra, CodigoItemListaServico vazio, ISS recalculado por alíquota Campos extras/removidos
3106200 Belo Horizonte PaisTomador="1058", DDDTomador separado, TelefoneTomador separado DDD separado
3549904 SJC DescricaoCidadePrestacao, CodigoCnae=tributacao, ValorUnitarioServico Campos extras
3543907 Rio Claro NaturezaTributacao do produto Natureza no produto
4115200 Londrina CNAE completo, URL encoding, ResponsavelRetencao CNAE + encoding
3530607 Marília ValorIss=0.00 fixo, CNAE completo ISS zerado
3509502 Campinas CodigoCnae=tributacao, multi-itens, ValorUnitarioServico Multi-item
5300108 Brasília/DF CodigoCnae=tributacao, CodigoTributacaoMunicipio vazio CNAE especial
1302603 Manaus DataEmissao truncada (somente data, sem hora) Data truncada
4314902 Porto Alegre PaisTomador=nome_do_pais Nome do país
2301000 Caucaia/CE Se ISS não retido: remove ValorIssRetido do TX2 Campo removido
3304557 Rio de Janeiro ValorUnitarioServico calculado Valor unitário
3303906 Petrópolis ValorUnitarioServico calculado Valor unitário
3201308 Vitória/ES PaisTomador="1058" Código fixo
5107040 Cuiabá PaisTomador="1058" Código fixo

Dados de Imóvel/Obra (Construção Civil)

Condição Triggered por Campos TX2 gerados
product.l10n_br_infendobraimovel in ['obra','ambos'] Produto com indicação de obra (ou ambos) EnderecoObra, NumeroObra, BairroObra, ComplementoObra, CodigoCidadeObra, DescricaoCidadeObra, UfObra, CepObra, PaisObra, CodigoCIB — todos do partner_imovel_id
product.l10n_br_infendobraimovel in ['imovel','ambos'] Produto com indicação de imóvel (ou ambos) LogradouroImovel, NumeroImovel, BairroImovel, ComplementoImovel, CodigoCidadeImovel, DescricaoCidadeImovel, EstadoProvinciaImovel, CodigoPostalImovel, CodigoPaisImovel, InscricaoFiscalImovel, CodigoCIB — todos do partner_imovel_id
product.l10n_br_infendobraimovel = 'ambos' Produto com indicação de ambos Gera os dois blocos (Obra + Imóvel) simultaneamente
invoice.l10n_br_codigo_obra preenchido Código de obra manual CodigoObra

Pré-requisito: invoice.partner_imovel_id deve estar preenchido (erro UserError se não estiver). Onde configurar: ✅ Fatura → "Imóvel" (parceiro tipo imóvel)

Campos de Obra detalhados

Campo TX2 Origem Como Alterar
EnderecoObra partner_imovel_id.street ✅ Parceiro imóvel → Endereço
NumeroObra partner_imovel_id.l10n_br_endereco_numero ✅ Parceiro imóvel → Número
BairroObra partner_imovel_id.l10n_br_endereco_bairro ✅ Parceiro imóvel → Bairro
ComplementoObra partner_imovel_id.street2 ✅ Parceiro imóvel → Complemento
CodigoCidadeObra partner_imovel_id.l10n_br_municipio_id.codigo_ibge ✅ Parceiro imóvel → Município
DescricaoCidadeObra partner_imovel_id.l10n_br_municipio_id.name Automático
UfObra partner_imovel_id.state_id.code ✅ Parceiro imóvel → Estado
CepObra partner_imovel_id.zip (formatado) ✅ Parceiro imóvel → CEP
PaisObra partner_imovel_id.country_id.code. Exceção: municípios específicos → fixo "1058" Automático (exceto municípios especiais)
CodigoCIB partner_imovel_id.l10n_br_codigo_cib ✅ Parceiro imóvel → Código CIB

Municípios com PaisObra fixo "1058"

4106902 (Curitiba), 3530607 (Marília), 4115200 (Londrina), 3505708 (Barueri), 3106200 (BH), 3509502 (Campinas), 3201308 (Vitória), 3549904 (SJC), 4205407 (Florianópolis), 4209003 (Joinville), 5107040 (Cuiabá), 3556453 (Votorantim)

Campos de Imóvel detalhados

Campo TX2 Origem Como Alterar
LogradouroImovel partner_imovel_id.street ✅ Parceiro imóvel → Endereço
NumeroImovel partner_imovel_id.l10n_br_endereco_numero ✅ Parceiro imóvel → Número
BairroImovel partner_imovel_id.l10n_br_endereco_bairro ✅ Parceiro imóvel → Bairro
ComplementoImovel partner_imovel_id.street2 ✅ Parceiro imóvel → Complemento
CodigoCidadeImovel partner_imovel_id.l10n_br_municipio_id.codigo_ibge ✅ Parceiro imóvel → Município
DescricaoCidadeImovel partner_imovel_id.l10n_br_municipio_id.name Automático
EstadoProvinciaImovel partner_imovel_id.state_id.code ✅ Parceiro imóvel → Estado
CodigoPostalImovel partner_imovel_id.zip (formatado) ✅ Parceiro imóvel → CEP
CodigoPaisImovel partner_imovel_id.country_id.code. Exceção: municípios específicos → fixo "1058" Automático
InscricaoFiscalImovel partner_imovel_id.l10n_br_inscricao_fiscal_imovel ✅ Parceiro imóvel → Inscrição Fiscal
CodigoCIB partner_imovel_id.l10n_br_codigo_cib ✅ Parceiro imóvel → Código CIB

⚠️ Bug potencial: O compute show_partner_imovel na fatura verifica apenas ['obra','imovel'] e não inclui 'ambos'. Isso pode fazer com que a seção de imóvel não seja visível na tela quando o produto está configurado como 'ambos'. Exige validação humana e possível correção no código.


Hooks de Herança

Hook Para que serve
_gerar_nfse_tx2_hook(invoice_vals, invoice_emit_vals) Customizar campos NFS-e sem alterar core

Troubleshooting — Rastreabilidade

Sintoma Campo TX2 Investigar em Cadeia
NFS-e rejeitada por código de serviço CodigoItemListaServico Produto → l10n_br_codigo_servico Produto → Cadastro → NFS-e
ISS não retido quando deveria ValorIssRetido 1º Operação Fiscal → alíquota retenção ISS. 2º Motor fiscal Operação → Motor → Linha
ISS retido indevidamente IssRetido Verificar l10n_br_iss_ret_valor na linha Motor fiscal
"Mais de 1 item" Parâmetro unificar_item_nfse ou município não suporta Parâmetro + município
CNAE incorreto CodigoCnae Depende do município — ver tabela de variações Empresa/Produto
Discriminação truncada DiscriminacaoServico Caracteres especiais na descrição _format_descservico()
PIS/COFINS zerados no JSON retencao.pis/cofins l10n_br_pis_ret_valor e l10n_br_cofins_ret_valor Motor fiscal → Operação
Exterior sem ISS ExigibilidadeISS Produto → l10n_br_exigibilidade_iss deve ser 4 (exportação) Produto
ValorUnitarioServico errado ValorUnitarioServico Somente municípios específicos calculam. Verificar município Código + município

Referências Cruzadas