Cálculo de Impostos¶
Objetivo¶
Documentar o motor de cálculo de impostos da localização brasileira CIEL IT, que é o componente mais complexo do sistema. Este motor determina automaticamente os impostos aplicáveis em cada transação, baseando-se em operações fiscais, tabelas NCM/UF e configurações da empresa.
Implementação Técnica¶
Métodos Principais¶
| Método | Modelo | Arquivo | Linha | Responsabilidade |
|---|---|---|---|---|
simulate_impostos() |
SaleOrder |
sale_order.py |
673 | Simulação fiscal completa para pedidos de venda |
_handle_taxes() |
SaleOrderLine |
sale_order.py |
3407 | Cria/busca account.tax e aplica ao item |
_handle_taxes() |
AccountMoveLine |
account.py |
8931 | Cria/busca account.tax e aplica à linha da fatura |
_handle_taxes() |
PurchaseOrderLine |
purchase.py |
953 | Variante para compras |
generate_all_taxes() |
ResCompany |
res_company.py |
461 | Pré-geração de template de impostos |
_get_ibpt() |
ResCompany |
res_company.py |
433 | Cálculo do valor aproximado de tributos |
Fluxo Geral do Cálculo¶
flowchart TD
A["Pedido/Fatura<br/>(trigger)"] --> B["Determinar Tipo<br/>de Produto"]
B --> C["Determinar Tipo<br/>de Cliente"]
C --> D["Determinar Destino<br/>(Intra/Inter/Ext)"]
D --> E["Buscar NCM/UF<br/>(4 tabelas)"]
E --> F["Buscar Operação<br/>(domain + order)"]
F --> G["Selecionar CFOP<br/>(Intra/Inter/Ext)"]
G --> H{"Operação<br/>encontrada?"}
H -->|Sim| I["Aplicar Parâmetros<br/>da Operação"]
H -->|Não| J["Erro / Sem impostos"]
I --> K["Calcular ICMS"]
K --> L["Calcular ICMS ST"]
L --> M["Calcular IPI"]
M --> N["Calcular PIS/COFINS"]
N --> O["Calcular ISS"]
O --> P["Calcular Retenções"]
P --> Q["Calcular IBS/CBS/IS"]
Q --> R["Calcular DIFAL/FCP"]
R --> S["Calcular IBPT"]
S --> T["Gerar account.tax<br/>(_handle_taxes)"]
Etapa 1: Determinação do Contexto¶
Tipo de Produto (l10n_br_tipo_produto)¶
if product.type == 'service' or product.l10n_br_codigo_servico:
tipo_produto = 'servico'
elif product.type == 'consu':
tipo_produto = 'consumivel'
elif product.purchase_ok:
tipo_produto = 'comprado'
else:
tipo_produto = 'produzido'
Tipo de Cliente (l10n_br_tipo_cliente)¶
if partner.l10n_br_cpf:
tipo_cliente = 'pf' # Pessoa Física
if company.country_id != partner.country_id:
tipo_cliente = 'ex' # Exterior
if partner.l10n_br_is:
tipo_cliente = 'zf' # Zona Franca
# default: 'pj' (Pessoa Jurídica)
Destino da Operação¶
if company.state_id == partner.state_id:
destino = '1' # Interna (mesma UF)
elif company.country_id != partner.country_id:
destino = '3' # Exterior
else:
destino = '2' # Interestadual
Etapa 2: Busca de Exceções NCM/UF¶
O motor consulta 4 tabelas de exceção na seguinte ordem de prioridade (a mais específica sobrescreve):
1. l10n_br_ciel_it_account.ncm.uf
→ Filtro: NCM + UF Origem + UF Destino
2. l10n_br_ciel_it_account.ncm.origem.uf
→ Filtro: NCM + UF Origem + UF Destino + Origem Mercadoria
→ Sobrescreve (1) se encontrada
3. l10n_br_ciel_it_account.ncm.ie.uf
→ Filtro: NCM + UF Origem + UF Destino + Origem + Indicador IE
→ Sobrescreve (2) se encontrada
4. l10n_br_ciel_it_account.ncm.cliente.uf
→ Filtro: NCM + UF Origem + UF Destino + Cliente específico
→ Sobrescreve (3) se encontrada
Se encontrada, a tabela NCM/UF pode alterar: CST ICMS, alíquota ICMS, redução de base, ICMS ST (MVA, alíquota), FCP e mensagens fiscais.
Etapa 3: Busca da Operação Fiscal¶
O motor monta um domínio dinâmico (ORM domain) que combina todos os critérios do contexto:
| Critério | Fonte |
|---|---|
| Tipo de operação | Fixo: saida ou entrada |
| Tipo de pedido | l10n_br_tipo_pedido do pedido |
| Empresa | company_id do pedido |
| Tipo de produto | Derivado do product.type |
| Tipo de cliente | Derivado do partner |
| Regime tributário | Do parceiro |
| Órgão público | Do parceiro |
| Indicador IE | Do parceiro |
| Origem mercadoria | Do produto |
| Destino operação | Derivado (Intra/Inter/Ext) |
| Tipo destinação | Do pedido (l10n_br_compra_indcom) |
| Operação ICMS ST | Se NCM/UF tem ICMS ST |
| Categoria produto | categ_id do produto |
| NCM | l10n_br_ncm_id do produto |
| Código serviço | l10n_br_codigo_servico |
| Produto específico | product_id |
| Tags fiscais | Do produto e do parceiro |
| UF do parceiro | state_id do parceiro |
| Município | l10n_br_municipio_id |
| Parceiro específico | partner_id |
| Valor mínimo | Total da NF |
Cada critério usa OR — aceita o valor específico OU o campo vazio (para match com operações genéricas).
A busca retorna 1 resultado (limit=1) com a ordem de prioridade definida no _order da operação (campos mais específicos primeiro, com _is_set DESC para priorizar registros com Many2many preenchidos).
Etapa 4: Determinação do CFOP¶
Após encontrar a operação, o CFOP é selecionado conforme o destino:
if company.state_id == partner.state_id:
cfop = operacao.l10n_br_intra_cfop_id # Mesmo estado
elif company.country_id != partner.country_id:
cfop = operacao.l10n_br_ext_cfop_id # Exterior
else:
cfop = operacao.l10n_br_inter_cfop_id # Interestadual
Etapa 5: Cálculo Individual dos Impostos¶
Para cada imposto, o motor:
1. Obtém a CST e alíquota da Operação Fiscal encontrada
2. Pode sobrescrever com dados do NCM/UF (se houver exceção)
3. Calcula a base de cálculo (preço unitário × quantidade + frete + seguro + despesas acessórias, com possíveis exclusões)
4. Calcula o valor do imposto (base × alíquota / 100)
5. Chama _handle_taxes() para criar ou reutilizar um registro account.tax
Cálculo do ICMS¶
- CST vem da Operação ou NCM/UF
- Base = Preço + Frete + Seguro + Despesas - (IPI se incluso) - (Desconto)
- Reduções aplicadas conforme
l10n_br_icms_reducao_base(%) - Alíquota pode vir da Operação ou NCM/UF
- Se empresa é Simples Nacional, pode aplicar
l10n_br_icms_credito_aliquota
Cálculo do ICMS ST¶
- Só calcula se CST indica ST (CST 10, 30, 60, 70, 201, 202, 203, 900)
- Base ST = (Base × MVA + FCP) ou conforme modalidade de base
- Valor ST = (Base ST × Alíquota ST) - ICMS Próprio
- Flag
l10n_br_icmsst_icmsfora: não subtrai ICMS próprio
Cálculo do IPI¶
- CST vem do CFOP ou da Operação
- Base = Preço + Frete + Seguro + Despesas
- Pode ser zerado (
l10n_br_ipi_zerar_base)
Cálculo do PIS/COFINS¶
- CST vem da Operação
- Base = Preço + Frete + Seguro + Despesas
- Se
l10n_br_exclui_icms_piscofins = True: Base -= ICMS ("Tese do Século") - Se
l10n_br_exclui_difal_piscofins = True: Base -= DIFAL - Pode ter redução de base (
l10n_br_pis_reducao_base,l10n_br_cofins_reducao_base)
Cálculo de Retenções¶
Para cada imposto retido (IRPJ, CSLL, PIS, COFINS, INSS, ISS):
1. Alíquota vem da Operação
2. Verifica valor mínimo de retenção do parceiro (l10n_br_irpj_ret_valor, etc.)
3. Só retém se o valor exceder o mínimo
Cálculo do DIFAL e FCP¶
- DIFAL: diferença entre alíquota interna da UF destino e alíquota interestadual
- FCP: alíquota adicional do Fundo de Combate à Pobreza (vem do NCM/UF)
- Controlado por
l10n_br_difal_regrana Operação
Cálculo IBS/CBS/IS (Reforma Tributária)¶
- CST vem da Operação
l10n_br_ibs_uf_aliquota× base +l10n_br_ibs_mun_aliquota× base +l10n_br_cbs_aliquota× base- Pode ter diferimento ou redução de alíquota
Etapa 6: Geração dos Impostos (_handle_taxes)¶
O método _handle_taxes() é chamado para cada imposto calculado. Ele:
- Busca um
account.taxtemplate (master) com nome no formato{IMPOSTO}[*]ou{IMPOSTO}-{UF}[*] - Se encontra o master, busca ou cria um imposto filho com os valores específicos
- Vincula o imposto à linha do documento (
tax_ids)
Convenção de nomes¶
| Padrão | Exemplo | Descrição |
|---|---|---|
{IMPOSTO}[*] |
ICMS[*] |
Template genérico |
{IMPOSTO}-{UF}[*] |
ICMS-SP[*] |
Template por UF de destino |
{IMPOSTO} {ALIQ}% |
ICMS 18% |
Imposto real com alíquota |
Hierarquia de busca do template¶
1. Tax com nome, amount_type, price_include, l10n_br_tipo_pedido + l10n_br_tipo_pedido_entrada, UF destino, empresa atual
2. Tax com nome, amount_type, price_include, UF destino, empresa atual
3. Tax com nome, amount_type, price_include, l10n_br_tipo_pedido, empresa pai
4. Tax com nome, amount_type, price_include, empresa pai
5. (sem UF) mesma sequência
IBPT — Valor Aproximado de Tributos¶
Método: _get_ibpt(ncm, l10n_br_origem, valor, servico=False)¶
Arquivo: res_company.py, linha 433
Fluxo¶
- Se produto é serviço: usa
l10n_br_ibpt_aliquota_servicoda empresa - Busca arquivo CSV em
static/ibpt/TabelaIBPTax{UF}{versão}.csv - Se encontrar o NCM no CSV: soma alíquotas (estadual + federal)
- Diferencia entre origem nacional e importada
- Fallback: usa alíquotas padrão configuradas na empresa
Cenários de Uso / Troubleshooting¶
1. Impostos não estão sendo calculados¶
- Verificar:
generate_all_taxes()foi executado na empresa? - Verificar: Existem templates
{IMPOSTO}[*]no registro de impostos? - Verificar: O tipo de uso do imposto (
type_tax_use) corresponde ao tipo do documento?
2. ICMS com alíquota incorreta¶
- Verificar: Existe registro na tabela NCM/UF que está sobrescrevendo a operação?
- Verificar: A operação mais específica está sendo selecionada (verificar
_order)?
3. PIS/COFINS com base incorreta¶
- Verificar:
l10n_br_exclui_icms_piscofinsestá configurado corretamente na empresa? - Verificar: A CST de PIS/COFINS na operação corresponde ao regime (cumulativo vs. não-cumulativo)?
4. Retenções não estão sendo aplicadas¶
- Verificar: Os valores mínimos de retenção no parceiro (
l10n_br_irpj_ret_valor, etc.) - Verificar: As alíquotas de retenção na operação estão preenchidas
5. ICMS ST não calculado¶
- Verificar: NCM/UF tem
l10n_br_icmsst_modalidade_basepreenchido? - Verificar: Operação tem
l10n_br_operacao_icmsstcorreto? - Verificar: IE ST cadastrada para a combinação UF na tabela
iest.uf
Referências Cruzadas¶
- Anterior: Operações Fiscais
- Próximo: Notas Fiscais
- Operações: Operações Fiscais e CFOPs
- NCM/UF: Produtos
- Empresa (contas contábeis): Configuração da Empresa
- Apuração: Apuração de Impostos
- Índice: Sumário Geral