Skip to content

Instantly share code, notes, and snippets.

@tporto
Last active June 9, 2025 23:10
Show Gist options
  • Save tporto/0d396539b7bd338770d87e05815b2839 to your computer and use it in GitHub Desktop.
Save tporto/0d396539b7bd338770d87e05815b2839 to your computer and use it in GitHub Desktop.
calculo de imposto nf 4.0
//itens
list_itens := TListNf_itens.Create();
for venda_item in venda_itens do
begin
produto := TProdutoController.getById(venda_item.ID_PRODUTO);
icms := TTributo_icms_ufController.get_by_grupo_uf(produto.ID_GRUPO_TRIBUTARIO, empresa_logado.UF);
ipi := TTributo_ipiController.get_by_grupo(produto.ID_GRUPO_TRIBUTARIO);
pis := TTributo_pisController.get_by_grupo(produto.ID_GRUPO_TRIBUTARIO);
cofins := TTributo_cofinsController.get_by_grupo(produto.ID_GRUPO_TRIBUTARIO);
//pegar o icms do destinatario, se ele for de outro estado
if (venda.ID_CLIENTE > 0) and (endereco.UF <> empresa_logado.UF) then
icms_dest := TTributo_icms_ufController.get_by_grupo_uf(produto.ID_GRUPO_TRIBUTARIO, endereco.UF)
else
icms_dest := icms; //se não, pego a do estado, para efeito de calculos
nf_item := TNf_itens.Create;
nf_item.ID_PRODUTO := produto.ID;
nf_item.CEST := produto.CEST;
nf_item.NUMERO_ITEM := venda_item.ORDEM;
nf_item.CODIGO_PRODUTO := inttostr(venda_item.ID_PRODUTO);
nf_item.GTIN := produto.GTIN;
nf_item.NOME_PRODUTO := produto.NOME;
nf_item.NCM := produto.NCM;
nf_item.CFOP := icms.CFOP;
nf_item.UNIDADE_COMERCIAL := venda_item.UNIDADE_SIGLA;
nf_item.QUANTIDADE_COMERCIAL := venda_item.QUANTIDADE;
nf_item.VALOR_UNITARIO_COMERCIAL := venda_item.VALOR_UNITARIO;
nf_item.VALOR_BRUTO_PRODUTO := venda_item.VALOR_SUBTOTAL;
nf_item.GTIN_UNIDADE_TRIBUTAVEL := produto.GTIN;
nf_item.UNIDADE_TRIBUTAVEL := venda_item.UNIDADE_SIGLA;
nf_item.QUANTIDADE_TRIBUTAVEL := venda_item.QUANTIDADE;
nf_item.VALOR_UNITARIO_TRIBUTAVEL := venda_item.VALOR_UNITARIO;
nf_item.VALOR_DESCONTO := venda_item.VALOR_DESCONTO;
//Base do IPI = Produto + Frete + Seguro + Outras Despesas Acessórias;
cur_vlrbase_ipi := venda_item.VALOR_SUBTOTAL + nf_item.VALOR_FRETE + nf_item.VALOR_OUTRAS_DESPESAS +
nf_item.VALOR_SEGURO;
if ipi.ALIQUOTA_PORCENTO > 0 then
begin
nf_item.IPI_ALIQUOTA := ipi.ALIQUOTA_PORCENTO;
nf_item.IPI_CST := ipi.CST_IPI;
nf_item.IPI_VALOR_BASE_CALCULO := cur_vlrbase_ipi;
nf_item.IPI_VALOR := (ipi.ALIQUOTA_PORCENTO / 100) * cur_vlrbase_ipi;
end
else
cur_vlrbase_ipi := 0;
//Base do PIS e COFINS (falta um teste em relação ao FRETE , se é DESTINATARIO ou EMITENTE)
cur_vlrbase_piscofins := (venda_item.VALOR_SUBTOTAL + nf_item.IPI_VALOR + nf_item.VALOR_FRETE + nf_item.VALOR_OUTRAS_DESPESAS +
nf_item.VALOR_SEGURO)
-
nf_item.VALOR_DESCONTO;
//Base do ICMS = Produto + Frete + Seguro + Outras Despesas Acessórias + IPI – Descontos
cur_vlrbase_icms := (venda_item.VALOR_SUBTOTAL + nf_item.IPI_VALOR + nf_item.VALOR_FRETE + nf_item.VALOR_OUTRAS_DESPESAS +
nf_item.VALOR_SEGURO)
-
nf_item.VALOR_DESCONTO;
//se o IPI compoe a base do icms
if (empresa_logado.INDUSTRIA = 'S') and (destinatario.INDICADOR_IE = 9) and
(empresa_logado.CRT <> 1) and (nf_item.IPI_VALOR > 0) then
begin
cur_vlrbase_icms := cur_vlrbase_icms + nf_item.IPI_VALOR;
end;
//Base do icms st = (produto + Valor do IPI + Frete + Seguro + Outras Despesas Acessórias – Descontos) * (1+(%MVA / 100))
cur_vlrbase_icms_st := cur_vlrbase_icms * (1 + (produto.PERCENTUAL_MVA / 100));
//Redução base calculo %
if (AnsiMatchStr(icms.CST_B, ['20', '51', '70'])) or
(AnsiMatchStr(icms.CSOSN_B, ['201', '202', '203'])) then
begin
if icms.REDUCAO_BC > 0 then
cur_vlrbase_icms := cur_vlrbase_icms - ((icms.REDUCAO_BC / 100) * cur_vlrbase_icms);
if icms.REDUCAO_BC_ST > 0 then
cur_vlrbase_icms_st := cur_vlrbase_icms_st - ((icms.REDUCAO_BC_ST / 100) * cur_vlrbase_icms_st);
nf_item.ICMS.PERCENTUAL_REDUCAO_BC_ICMS_ST := icms.REDUCAO_BC_ST;
nf_item.ICMS.TAXA_REDUCAO_BC_ICMS := icms.REDUCAO_BC;
end;
//icms
//simples nacional
if emitente.CRT = '1' then
begin
nf_item.ICMS.ORIGEM_MERCADORIA := produto.TRIBUTO.ORIGEM_MERCADORIA;
nf_item.ICMS.CSOSN := icms.CSOSN_B;
//CSON (Crédito simples nacional)
if (AnsiMatchStr(nf_item.ICMS.CSOSN, ['101', '201'])) and (empresa_logado.ALIQUOTA_CREDITO_ICMS > 0) then
begin
nf_item.ICMS.ALIQUOTA_CREDITO_ICMS_SN := empresa_logado.ALIQUOTA_CREDITO_ICMS;
nf_item.ICMS.VALOR_CREDITO_ICMS_SN := (nf_item.ICMS.ALIQUOTA_CREDITO_ICMS_SN / 100) * cur_vlrbase_icms;
end;
end;
//Regime normal
if emitente.CRT = '3' then
begin
nf_item.ICMS.CST_ICMS := icms.CST_B;
nf_item.ICMS.MODALIDADE_BC_ICMS := icms.MODALIDADE_BC;
nf_item.ICMS.BASE_CALCULO_ICMS := cur_vlrbase_icms;
//aliquotas icms
nf_item.ICMS.ALIQUOTA_ICMS := icms.ALIQUOTA_INTERNA;
if icms.ALIQUOTA > 0 then
nf_item.ICMS.ALIQUOTA_ICMS := icms.ALIQUOTA; //Aliquota diferenciada icms
nf_item.ICMS.VALOR_ICMS := (nf_item.ICMS.ALIQUOTA_ICMS / 100) * cur_vlrbase_icms;
//ICMS Diferimento (ICMS 51 - TRIBUTADO COM DIFERIMENTO)
if (nf_item.ICMS.CST_ICMS = '51') and (icms.PERCENTUAL_DIFERIMENTO > 0) then
begin
nf_item.ICMS.PERCENTUAL_DIFERIMENTO := icms.PERCENTUAL_DIFERIMENTO;
nf_item.ICMS.VALOR_ICMS_DIFERIDO := (icms.PERCENTUAL_DIFERIMENTO / 100) * nf_item.ICMS.VALOR_ICMS;
nf_item.ICMS.VALOR_ICMS := nf_item.ICMS.VALOR_ICMS - nf_item.ICMS.VALOR_ICMS_DIFERIDO;
end;
//FCP
if AnsiMatchStr(nf_item.ICMS.CST_ICMS, ['00', '10', '20', '51', '70', '90']) then
begin
if AnsiMatchStr(nf_item.ICMS.CST_ICMS, ['10', '20', '51', '70', '90']) then
nf_item.ICMS.VALOR_BC_FPC := cur_vlrbase_icms;
nf_item.ICMS.PERCENTUAL_FPC := icms.FCP;
nf_item.ICMS.VALOR_FPC := (icms.FCP / 100) * cur_vlrbase_icms;
end;
end;
//ICMS ST
if (AnsiMatchStr(nf_item.ICMS.CST_ICMS, ['10', '30', '60', '70', '90'])) or
(AnsiMatchStr(nf_item.ICMS.CSOSN, ['201', '202', '203', '500', '900'])) then
begin
nf_item.ICMS.PERCENTUAL_MVA_ICMS_ST := produto.PERCENTUAL_MVA; //MVA %
nf_item.ICMS.MODALIDADE_BC_ICMS_ST := icms.MODALIDADE_BC_ST;
//aliquota icms st
nf_item.ICMS.ALIQUOTA_ICMS_ST := icms.ALIQUOTA_INTERNA;
if icms.ALIQUOTA_ICMS_ST > 0 then
nf_item.ICMS.ALIQUOTA_ICMS_ST := icms.ALIQUOTA_ICMS_ST; //Aliquota diferenciada icms st
nf_item.ICMS.VALOR_BASE_CALCULO_ICMS_ST := cur_vlrbase_icms_st; //Devo usar mesmo a aliquota interna do destinatario???
nf_item.ICMS.VALOR_ICMS_ST := (cur_vlrbase_icms_st * (icms_dest.ALIQUOTA_INTERNA / 100)) - nf_item.ICMS.VALOR_ICMS;
if nf_item.ICMS.VALOR_ICMS_ST < 0 then
nf_item.ICMS.VALOR_ICMS_ST := 0;
//FCP ST
if ((AnsiMatchStr(nf_item.ICMS.CST_ICMS, ['10', '30', '70', '90'])) or
(AnsiMatchStr(nf_item.ICMS.CSOSN, ['201', '202', '203', '900']))) then
begin
if icms.FCP > 0 then
begin
nf_item.ICMS.VALOR_BC_FPC_ST := cur_vlrbase_icms_st;
nf_item.ICMS.PERCENTUAL_BC_FPC_ST := icms.FCP;
nf_item.ICMS.VALOR_FPC_ST := (icms.FCP / 100) * cur_vlrbase_icms_st;
end;
end;
end
else
cur_vlrbase_icms_st := 0; //Zerar a base icms st?
//ST
if ((nf_item.ICMS.CST_ICMS = '60') or (nf_item.ICMS.CSOSN = '500')) and (icms.FCP > 0) then
nf_item.ICMS.FPC_CONSUMIDOR_FINAL := icms.ALIQUOTA_INTERNA + icms.FCP; //pST
//COFINS
if AnsiMatchStr(cofins.CST_COFINS, ['10', '20']) then
begin
nf_item.ALIQUOTA_COFINS_PERCENTUAL := empresa_logado.ALIQUOTA_COFINS;
if cofins.ALIQUOTA_PORCENTO > 0 then
nf_item.ALIQUOTA_COFINS_PERCENTUAL := cofins.ALIQUOTA_PORCENTO;
if nf_item.ALIQUOTA_COFINS_PERCENTUAL > 0 then
begin
nf_item.CST_COFINS := cofins.CST_COFINS;
nf_item.BASE_CALCULO_COFINS := cur_vlrbase_piscofins;
nf_item.VALOR_COFINS := (nf_item.ALIQUOTA_COFINS_PERCENTUAL / 100) * cur_vlrbase_piscofins;
nf_item.COFINS_QUANTIDADE_VENDIDA := venda_item.QUANTIDADE;
nf_item.ALIQUOTA_COFINS_REAIS := nf_item.ALIQUOTA_COFINS_PERCENTUAL / 100;
end;
end;
//PIS
if AnsiMatchStr(pis.CST_PIS, ['10', '20']) then
begin
nf_item.ALIQUOTA_PIS_PERCENTUAL := empresa_logado.ALIQUOTA_PIS;
if pis.ALIQUOTA_PORCENTO > 0 then
nf_item.ALIQUOTA_PIS_PERCENTUAL := pis.ALIQUOTA_PORCENTO;
if nf_item.ALIQUOTA_PIS_PERCENTUAL > 0 then
begin
nf_item.CST_PIS := pis.CST_PIS;
nf_item.VALOR_BASE_CALCULO_PIS := cur_vlrbase_piscofins;
nf_item.PIS_QUANTIDADE_VENDIDA := venda_item.QUANTIDADE;
nf_item.VALOR_PIS := (nf_item.ALIQUOTA_PIS_PERCENTUAL / 100) * cur_vlrbase_piscofins;
nf_item.ALIQUOTA_PIS_REAIS := nf_item.ALIQUOTA_PIS_PERCENTUAL / 100;
end;
end;
//operação interestadual
if (venda.ID_CLIENTE > 0) and (endereco.UF <> empresa_logado.UF) then
begin
cur_difal := cur_vlrbase_icms * ((icms.ALIQUOTA_INTERNA - icms.ALIQUOTA_INTERESTADUAL) / 100);
nf_item.ICMS.VALOR_BC_ICMS_UF_DESTINO := cur_vlrbase_icms; //vBCUFDest
nf_item.ICMS.PERCENTUAL_FPC_UF_DESTINO := icms_dest.FCP; //pFCPUFDest
nf_item.ICMS.ALIQUOTA_INTERNA_UF_DESTINO := icms_dest.ALIQUOTA_INTERNA; //pICMSUFDest
nf_item.ICMS.ALIQUOTA_INTERESTADUAL_UFS := icms.ALIQUOTA_INTERESTADUAL; //pICMSInter
case YearOf(now) of
2018: begin
nf_item.ICMS.PERCENTUAL_PROVISORIO_PARTILHA := 80; //pICMSInterPart
nf_item.ICMS.VALOR_ICMS_FPC_UF_DESTINO := nf_item.ICMS.VALOR_FPC; //vFCPUFDest
nf_item.ICMS.VALOR_ICMS_INTER_UF_DESTINO := cur_difal * (80 / 100); //vICMSUFDest
nf_item.ICMS.VALOR_ICMS_INTER_UF_REMETENTE := cur_difal * (20 / 100); //vICMSUFRemet
end;
2019: begin
nf_item.ICMS.PERCENTUAL_PROVISORIO_PARTILHA := 100; //pICMSInterPart
nf_item.ICMS.VALOR_ICMS_FPC_UF_DESTINO := nf_item.ICMS.VALOR_FPC; //vFCPUFDest
nf_item.ICMS.VALOR_ICMS_INTER_UF_DESTINO := cur_difal; //vICMSUFDest
nf_item.ICMS.VALOR_ICMS_INTER_UF_REMETENTE := 0; //vICMSUFRemet
end;
else
begin
nf_item.ICMS.PERCENTUAL_PROVISORIO_PARTILHA := 100; //pICMSInterPart
nf_item.ICMS.VALOR_ICMS_FPC_UF_DESTINO := nf_item.ICMS.VALOR_FPC; //vFCPUFDest
nf_item.ICMS.VALOR_ICMS_INTER_UF_DESTINO := cur_difal; //vICMSUFDest
nf_item.ICMS.VALOR_ICMS_INTER_UF_REMETENTE := 0; //vICMSUFRemet
end;
end;
end;
//fazer a leitura da tabela ibpt para poder pegar os tributos
nf_item.valor_total_tributos := 0;
ncm := TNcmController.get_by_codigo(produto.NCM);
if ncm <> nil then
begin
nf_item.valor_total_tributos := (nf_item.VALOR_BRUTO_PRODUTO - nf_item.VALOR_DESCONTO) *
((ncm.ALIQUOTA_ESTADUAL + ncm.ALIQUOTA_NACIONAL + ncm.ALIQUOTA_MUNICIPAL) / 100);
end;
cur_vlrtributos += nf_item.valor_total_tributos;
//Quando zerar as bases? Está certo assim?
if (AnsiMatchStr(nf_item.ICMS.CST_ICMS, ['30', '40', '41', '50', '60'])) or
(AnsiMatchStr(nf_item.ICMS.CSOSN, ['101', '102', '103', '300', '400', '500'])) then
begin
cur_vlrbase_icms := 0;
nf_item.ICMS.ALIQUOTA_ICMS := 0;
nf_item.ICMS.VALOR_ICMS := 0;
nf_item.ICMS.BASE_CALCULO_ICMS := 0;
//icms st
if nf_item.ICMS.CST_ICMS <> '30' then
begin
cur_vlrbase_icms_st := 0;
nf_item.ICMS.VALOR_BASE_CALCULO_ICMS_ST := 0;
nf_item.ICMS.VALOR_ICMS_ST := 0;
nf_item.ICMS.ALIQUOTA_ICMS_ST := 0;
end;
end;
if AnsiMatchStr(nf_item.ICMS.CSOSN, ['201', '202', '203']) then
begin
cur_vlrbase_icms := 0;
nf_item.ICMS.ALIQUOTA_ICMS := 0;
nf_item.ICMS.VALOR_ICMS := 0;
nf_item.ICMS.BASE_CALCULO_ICMS := 0;
end;
//totais
nf.base_calculo_icms := nf.base_calculo_icms + cur_vlrbase_icms; //vBC - Base de Calculo do ICMS
nf.valor_fpc := nf.valor_fpc + nf_item.ICMS.VALOR_FPC; //vFCP - Valor Total do FCP (Fundo de Combate a Pobreza)
nf.valor_fpc_st := nf.valor_fpc_st + nf_item.ICMS.VALOR_FPC_ST; //vFCPST - Valor Total do FCP (Fundo de Combate a Pobreza) retido por substituicao tributaria
nf.valor_icms := nf.valor_icms + nf_item.ICMS.VALOR_ICMS; //vICMS - Valor Total do ICMS
nf.base_calculo_icms_st := nf.base_calculo_icms_st + cur_vlrbase_icms_st; //vBCST - Base de Calculo do ICMS ST
nf.valor_icms_st := nf.valor_icms_st + nf_item.ICMS.VALOR_ICMS_ST; //vST - Valor Total do ICMS ST
nf.valor_frete := nf.valor_frete + nf_item.VALOR_FRETE; //vFrete - Valor Total do Frete
nf.valor_ipi := nf.valor_ipi + nf_item.IPI_VALOR; //vIPI - Valor Total do IPI
nf.valor_pis := nf.valor_pis + nf_item.VALOR_PIS; //vPIS - Valor do PIS
nf.valor_cofins := nf.valor_cofins + nf_item.VALOR_COFINS; //vCOFINS - Valor do COFINS - Valor do COFINS
nf.valor_despesas_acessorias := nf.valor_despesas_acessorias + nf_item.VALOR_OUTRAS_DESPESAS; //vOutro - Outras Despesas acessorias
nf.valor_icms_fpc_uf_destino := nf.valor_icms_fpc_uf_destino + nf_item.ICMS.VALOR_ICMS_FPC_UF_DESTINO; //vFCPUFDest - Valor total do ICMS relativo ao Fundo de Combate a Pobreza (FCP) para a UF de destino.
nf.valor_icms_inter_uf_destino := nf.valor_icms_inter_uf_destino + nf_item.ICMS.VALOR_ICMS_INTER_UF_DESTINO; //vICMSUFDest - Valor total do ICMS Interestadual para a UF de destino (sem o valor do ICMS relativo ao FCP).
nf.valor_icms_inter_uf_remetente := nf.valor_icms_inter_uf_remetente + nf_item.ICMS.VALOR_ICMS_INTER_UF_REMETENTE;
list_itens.Add(nf_item);
end;
nf.VALOR_TOTAL_PRODUTO := venda.VALOR_SUBTOTAL; //vProd - Valor Total do produto
nf.VALOR_DESCONTO := venda.VALOR_DESCONTO; //vDesc - Valor Total do desconto
nf.VALOR_SEGURO := venda.VALOR_SEGURO; //vSeg - Valor Total do Seguro
nf.valor_total := (
nf.VALOR_TOTAL_PRODUTO +
nf.valor_icms_st +
nf.valor_frete +
nf.VALOR_SEGURO +
nf.valor_despesas_acessorias +
nf.VALOR_FPC_ST +
nf.valor_ipi -
nf.VALOR_DESCONTO
); //vNF - Valor Total da NF-e [(+) vProd (id:W07) (-) vDesc (id:W10) (+) vICMSST (id:W06) (+) vFrete (id:W09) (+) vSeg (id:W10) (+) vOutro (id:W15) (+) vII (id:W11) (+) vIPI (id:W12) (+) vServ (id:W19) (NT 2011/004)]
nf.INFORMACOES_ADD_CONTRIBUINTE := FormatFloat('Voce pagou aproximadamente: R$ ,#0.00 de tributos', cur_vlrtributos); //infCpl - Informacoes Complementares de interesse do Contribuinte
if venda.OBSERVACAO <> '' then
nf.INFORMACOES_ADD_CONTRIBUINTE := venda.OBSERVACAO + #13 +
FormatFloat('Voce pagou aproximadamente: R$ ,#0.00 de tributos', cur_vlrtributos);//vNF - Valor Total da NF-e [(+) vProd (id:W07) (-) vDesc (id:W10) (+) vICMSST (id:W06) (+) vFrete (id:W09) (+) vSeg (id:W10) (+) vOutro (id:W15) (+) vII (id:W11) (+) vIPI (id:W12) (+) vServ (id:W19) (NT 2011/004)]
//DÚVIDAS
// 1 - O ICMS-ST e o FCP-ST são apenas para operações interestaduais?
// 2 - Eu tenho que ter um CSON para operação interna e outro para externa?
// 3 - Estou em dúvida nesse código em relação ao CST=60 para não calcular o imposto.
// 4 - Esse meu cadastro de grupo tributário tá legal?
// 5 - Dessa forma está preparado para emissão de NFC-e?
// 6 - Estava olhando um cadastro de empresas de um sistema e lá tem um campo para informar o faturamento da empresa anual, é necessário mesmo?
@tporto
Copy link
Author

tporto commented Jun 20, 2018

Criei uma tabela para salvar as informações pré-configuradas, para depois jogar no ACBR.

@tporto
Copy link
Author

tporto commented Jun 20, 2018

empresa
grupo
produto

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment