Pular para o conteúdo principal

PC_MARGEMVENDA - Percentual de Margem de Venda (fallback da empresa)

Tela: MFA001 - Parâmetros de Faturamento Localização: Parâmetros → Ambos → Opção 1 → campo % Margem Venda (rotulado [MNF017] na tela) Tabela: PARMFATUR.PC_MARGEMVENDA Tipo: Numérico (percentual %) - DOM_NUMERIC3_2 Valor padrão: NULL (vazio - nenhum default é atribuído no AfterInsert do MFA001) Validação: deve ser maior ou igual a zero (W-0000 "O Percentual deve ser Maior ou Igual a Zero!").

O que o parâmetro faz​

PC_MARGEMVENDA é a margem percentual padrão da empresa usada como último nível de fallback no cálculo do preço de venda quando o sistema precisa recalcular preço a partir do custo de entrada (nota fiscal de entrada, formação de preço, recálculo de tabela, etc.).

A cadeia de precedência adotada em todo o ERP ao determinar a margem a aplicar é, do mais específico ao mais genérico:

ITEMTABPRECO.PC_MARGEM (item/tabela específica)
> ITEM.PC_MARGEMLUCRO (margem cadastrada no produto TPO001)
> TABPRECO.PC_MARGEM (margem da tabela de preço)
> PARMFATUR.PC_MARGEMVENDA (este parâmetro - fallback da empresa)

No carregamento do MNF001, se PARMFATUR.PC_MARGEMVENDA estiver vazio, o sistema ainda busca de TABPRECO.PC_MARGEM da CD_TABPRECO configurada e usa esse valor como iPC_MARGEMVENDA (degradação adicional para o usuário que esqueceu de preencher).


Telas impactadas​

MóduloCódigoComo usa PC_MARGEMVENDA
Parâmetros FaturamentoMFA001Cadastro do próprio valor - TDBEdit edtPC_MARGEMVENDA no grupo Opção 1 (UMFA001.dfm:3125-3141)
NF EntradaMNF001Lê o parâmetro para dmMNF001.iPC_MARGEMVENDA e passa como PC_MARGEM para o tabCUSTO (Custo de Reposição) e para ATUALIZA_PRECOVENDA
Custo Reposição NF(unit UCUSTOREPOSICAONF / MNF001)Aplica a fórmula Vl_Fator = 1 - (Pc_Margem/100) quando ST_PRECOVENDA in ('D','B','G')
Formação de PreçoMPD014Usa coluna computada PC_MARGEMVENDA no grid de formação de preço (é valor calculado, não lido deste parâmetro)
Custo Cadastro FiscalCFA001, CFA002Carrega iPC_MARGEMVENDA da PARMFATUR ao validar empresa
Análise EstoqueCEQ003, CEQ007Carrega iPC_MARGEMVENDA da PARMFATUR para uso em análises
Custo NF ComplementarCNF005Busca PC_MARGEMVENDA em dmCNF005.iQTMARGEM
Configuração TributáriaCNF017Grid/update inclui PC_MARGEMVENDA no SELECT/UPDATE de PARMFATUR
Configuração PedidoCPD009Update de PARMFATUR inclui PC_MARGEMVENDA
Cadastro ProdutoTPO001Lê PC_MARGEMVENDA em dmTPO001.iQTMARGEM ao abrir
Relatório Custo/VendaRNF006Usa como fallback de PC_MARGEM em SELECT computado
Relatório NF EntradaRNF026COALESCE(I.PC_MARGEMLUCRO, TP.PC_MARGEM, PF.PC_MARGEMVENDA) PC_MARGEM
Relatório AnáliseRCA006Usa COALESCE(TI.PC_MARGEM, I.PC_MARGEMLUCRO, V.PC_MARGEM, PF.PC_MARGEMVENDA) PC_MARGEM

Procedures impactadas​

ProcedureArquivoUso
ATUALIZA_PRECOVENDAScripts/ATUALIZA_PRECOVENDA.sqlRecebe I_PC_MARGEMVENDA como parâmetro; se V_PC_MARGEMTAB IS NULL → V_PC_MARGEMTAB = I_PC_MARGEMVENDA e aplica nos cálculos de preço (métodos 1 e 2)
GERA_NOTAFISCALScripts/GERA_NOTAFISCAL.sqlLê P.PC_MARGEMVENDA de PARMFATUR em I_PC_MARGEMVENDA e repassa para ATUALIZA_PRECOVENDA na geração de nota
GERA_ESTOQUE_NOTAFISCALScripts/GERA_ESTOQUE_NOTAFISCAL.sqlLê P.PC_MARGEMVENDA de PARMFATUR em I_PC_MARGEMVENDA para atualização de estoque/preço
GERA_ESTOQUEScripts/GERA_ESTOQUE.sqlEm operação de entrada (I_TP_OPERACAO = 'E'), lê P.PC_MARGEMVENDA e repassa para ATUALIZA_PRECOVENDA
RECALCULA_PRECOVENDAScripts/RECALCULA_PRECOVENDA.sqlLê V_PC_MARGEMVENDA de PARMFATUR e repassa para ATUALIZA_PRECOVENDA no recálculo
RECALCULA_PRECOCOMPRAScripts/RECALCULA_PRECOCOMPRA.sqlFallback final em PC_MARGEM = V_PC_MARGEMVENDA quando margens mais específicas são nulas
RETORNA_CUSTOPRODUTOScripts/RETORNA_CUSTOPRODUTO.sqlRetorna PC_MARGEM = V_PC_MARGEMVENDA como último fallback no cálculo do custo/margem do produto
VIEW_CNF006Scripts/VIEW_CNF006.sqlCálculo de ICMS fiscal: COALESCE(I.PC_MARGEMLUCRO, P.PC_MARGEMVENDA)

Campos envolvidos​

CampoTabelaDescrição
PC_MARGEMVENDAPARMFATURMargem percentual padrão da empresa (este parâmetro)
PC_MARGEMLUCROITEMMargem específica do produto (prioridade maior)
PC_MARGEMTABPRECOMargem da tabela de preço (prioridade intermediária)
PC_MARGEMITEMTABPRECOMargem do item dentro de uma tabela específica (prioridade máxima)
ST_PRECOVENDAPARMFATURDefine QUAL fórmula de cálculo usa a margem (veja abaixo)
VL_UNITARIOITEMTABPRECO / ITEMNOTAPreço unitário gerado a partir do custo aplicando a margem
CD_TABPRECOPARMFATURTabela padrão usada como fallback de margem quando PC_MARGEMVENDA é nulo

Comportamento / Fórmula de aplicação​

PC_MARGEMVENDA sempre entra como percentual. Como é aplicado depende do parâmetro ST_PRECOVENDA (veja st_precovenda), que determina se o sistema usa markup "de cima" (sobre o custo) ou markdown "de baixo" (divisor).

Valor NULL ou não configurado​

O que aconteceDetalhe
Cadastro (MFA001)AfterInsert não atribui default - campo nasce vazio
Ao ler no MNF001Se vazio, o sistema tenta buscar TABPRECO.PC_MARGEM da tabela configurada (CD_TABPRECO) e usa esse valor
Ao passar na ATUALIZA_PRECOVENDASe nenhuma margem específica for encontrada (item/tabela/item+tabela) e PC_MARGEMVENDA também for nulo, a procedure não recalcula preço (condição IF ( (v_pc_margemitemtab IS NOT NULL) OR (v_pc_margemtab IS NOT NULL) OR (i_pc_margemitem IS NOT NULL) ) falha)
Efeito práticoO preço de venda do item não é recalculado automaticamente ao receber mercadoria; permanece o último preço já existente na tabela

Simulação passo a passo​

  1. Em MFA001 → Opção 1 → % Margem Venda = vazio (em branco).
  2. Certifique-se que a CD_TABPRECO configurada também não tem PC_MARGEM.
  3. Certifique-se que o produto também não tem PC_MARGEMLUCRO (TPO001).
  4. Lance uma nota fiscal de entrada em MNF001 com um produto cujo custo subiu.
  5. Resultado esperado: O preço na tabela de venda não é recalculado automaticamente - o sistema não tem base de margem para calcular o novo preço.

Valor > 0 (ex.: PC_MARGEMVENDA = 30,00)​

PC_MARGEMVENDA vira o fallback aplicado quando nem o item nem a tabela tiverem margem própria. A fórmula varia conforme ST_PRECOVENDA:

ST_PRECOVENDAFórmula (vide ATUALIZA_PRECOVENDA.sql e UCUSTOREPOSICAONF.pas)
'D', 'B', 'G' (Método 2 - "De Baixo" / markdown divisor)Vl_Fator = 1 - (Pc_Margem / 100) → Preco = Custo / Vl_Fator
Demais (Método 1 - "De Cima" / markup)Preco = Custo + (Custo * Pc_Margem / 100) equivalente a Preco = Custo * (1 + Pc_Margem/100)

Exemplos numéricos concretos​

Cenário 1: Markup "De Cima" (ex.: ST_PRECOVENDA = 'S' - Sim (saldo físico))

  • Custo = R$ 100,00; PC_MARGEMVENDA = 30,00
  • Preco = 100 + (100 * 30 / 100) = 100 + 30 = R$ 130,00
  • Margem efetiva sobre o custo = 30%; margem sobre o preço de venda ≈ 23,08%

Cenário 2: Markdown "De Baixo" (ST_PRECOVENDA = 'D', 'B' ou 'G')

  • Custo = R$ 100,00; PC_MARGEMVENDA = 30,00
  • Vl_Fator = 1 - (30/100) = 0,70
  • Preco = 100 / 0,70 = R$ 142,857...
  • Margem sobre o preço de venda = 30% (exatamente); margem sobre o custo ≈ 42,86%

Cenário 3: Valor de borda do domínio (DOM_NUMERIC3_2 permite até 9,99)

  • PC_MARGEMVENDA = 9,99; Custo = R$ 100,00
  • Markup: Preco = 100 * 1,0999 = R$ 109,99
  • Observação: o domínio de coluna é NUMERIC(3,2) → máximo 9.99, embora a procedure ATUALIZA_PRECOVENDA declare NUMERIC(5,2). Valores acima de 9,99% não podem ser persistidos neste campo; margens maiores precisam ser configuradas em nível de tabela (TABPRECO.PC_MARGEM) ou de produto (ITEM.PC_MARGEMLUCRO).

Simulação passo a passo​

  1. Em MFA001 → Opção 1 → % Margem Venda = 5,00 (permitido) e ST_PRECOVENDA = qualquer método de recálculo.
  2. Certifique-se que o produto X não tem PC_MARGEMLUCRO (TPO001).
  3. Certifique-se que a tabela de preço configurada não tem PC_MARGEM nem registro ITEMTABPRECO com margem específica.
  4. Lance uma entrada de NF em MNF001 do produto X com custo R$ 100,00.
  5. Ao confirmar a nota, o GERA_NOTAFISCAL chama ATUALIZA_PRECOVENDA(..., I_PC_MARGEMVENDA = 5,00, ...).
  6. A procedure aplica a fórmula conforme ST_PRECOVENDA e grava o novo preço em ITEMTABPRECO.VL_PRECO.
  7. Resultado esperado: preço de venda do produto X é atualizado para R$ 105,00 (markup) ou R$ 105,26 (markdown, 100/0,95).

Referências no Código Fonte​

Delphi - MFA001 (cadastro do parâmetro)​

  • source/MFA001/UMFA001.dfm:3125-3141 - edtPC_MARGEMVENDA: TDBEdit com DataField = 'PC_MARGEMVENDA', ligado a dmMFA001.dsPARMFATUR.
  • source/MFA001/UMFA001.dfm:2407-2420 - Label lbl15 com Caption = '% Margem Venda', FocusControl = edtPC_MARGEMVENDA.
  • source/MFA001/UMFA001.dfm:2421-2434 - Label lbl30 com Caption = '[MNF017]' apontando para o edit.
  • source/MFA001/UMFA001.pas:239 - declaração edtPC_MARGEMVENDA: TDBEdit no form.
  • source/MFA001/UdmMFA001.pas:49 - tabPARMFATURPC_MARGEMVENDA: TBCDField.
  • source/MFA001/UdmMFA001.pas:1076-1080 - tabPARMFATURPC_MARGEMVENDAValidate:
procedure TdmMFA001.tabPARMFATURPC_MARGEMVENDAValidate(Sender: TField);
begin
if ( tabPARMFATURPC_MARGEMVENDA.AsFloat < 0 ) then
Raise JException.Create('W-0000', ['O Percentual deve ser Maior ou Igual a Zero!']);
end;
  • source/MFA001/UdmMFA001.pas:434-... - tabPARMFATURAfterInsert NÃO atribui valor a PC_MARGEMVENDA (nasce NULL).

Delphi - uso como fallback em MNF001​

  • source/MNF001/UdmMNF001.pas:1110 - variável pública iPC_MARGEMVENDA: String.
  • source/MNF001/UdmMNF001.pas:1375, 1401-1406 - leitura do parâmetro + fallback para TABPRECO.PC_MARGEM:
' ST_CUSTOREPOSICAO, CD_TABCOMPRA, PC_MARGEMVENDA, ' +
...
dmMNF001.iPC_MARGEMVENDA := Resultado[14];

if (Resultado[14] = '') then begin
Consulta := 'SELECT PC_MARGEM FROM TABPRECO WHERE CD_TABPRECO = '+ Nulo(Resultado[10], 'I');
dmMNF001.iPC_MARGEMVENDA := ExecutaConsulta(dmMNF001.transaction, Consulta)[0];
end;
  • source/MNF001/UMNF001.pas:2650 - repasse para tabCUSTO.ParamByName('PC_MARGEM') no recálculo de custo de reposição.
  • source/MNF001/UCUSTOREPOSICAONF.pas:269-280 - fórmula markdown:
if ( tabCUSTOPC_MARGEMLUCRO.AsString <> '' ) then
Pc_Margem := tabCUSTOPC_MARGEMLUCRO.AsFloat
else
if ( Trim(dmMNF001.iPC_MARGEMVENDA) <> '' ) then
Pc_Margem := StrToFloat(dmMNF001.iPC_MARGEMVENDA)
else
Pc_Margem := 0;

if ( (Trim(dmMNF001.iST_PRECOVENDA) = 'D') Or (Trim(dmMNF001.iST_PRECOVENDA) = 'B') Or (Trim(dmMNF001.iST_PRECOVENDA) = 'G' ) ) then
begin
Vl_Fator := 1 - (Pc_Margem / 100);
  • source/MNF001/UCUSTOREPOSICAONF.pas:336-337 - passagem para o dataset tabCUSTO.
  • source/MNF001/UFRETENF.pas:248-258, 560-567 - lê PC_MARGEMVENDA em iPcMargem e passa para ATUALIZA_PRECOVENDA.

Delphi - demais módulos consumidores​

  • source/CEQ003/UdmCEQ003.pas:68, 189, 208 - iPC_MARGEMVENDA declarada/usada na análise de estoque.
  • source/CEQ007/UdmCEQ007.pas:68 - mesma lógica de leitura via PARMFATUR.
  • source/CFA001/UdmCFA001.pas:142, 158, 178 - busca Pc_MargemVenda da PARMFATUR ao validar empresa.
  • source/CFA002/UdmCFA002.pas:142, 242, 261 - mesma lógica.
  • source/CNF005/UdmCNF005.pas:234-244 - lê PC_MARGEMVENDA em dmCNF005.iQTMARGEM.
  • source/CNF017/UdmCNF017.dfm:297, 443, 535 - grid update/select do PARMFATUR inclui PC_MARGEMVENDA.
  • source/CPD009/UdmCPD009.dfm:3046, 3192, 3284 - update de PARMFATUR inclui PC_MARGEMVENDA.
  • source/TPO001/UTPO001.pas:968-979 - busca PC_MARGEMVENDA em dmTPO001.iQTMARGEM no cadastro de produto.
  • source/MPD002/UMPD002.pas:5366 - PC_MARGEMVENDA como coluna computada no relatório de orçamento (cálculo em cima dos valores do item, não lê do PARMFATUR).
  • source/MPD014/UdmMPD014.dfm:743, 794-803 / UdmMPD014.pas:82, 190 - coluna computada na formação de preço.
  • source/RNF006/URNF006.pas:1351, 1354 - PC_MARGEMVENDA calculado no SQL do relatório (não lê do PARMFATUR; é cálculo interno).
  • source/RNF026/UdmRNF026.pas:119 - COALESCE(I.PC_MARGEMLUCRO, TP.PC_MARGEM, PF.PC_MARGEMVENDA) PC_MARGEM.
  • source/RCA006/UdmRCA006.dfm:554-559 - COALESCE(TI.PC_MARGEM, I.PC_MARGEMLUCRO, V.PC_MARGEM, PF.PC_MARGEMVENDA) PC_MARGEM.

SQL - Procedures​

  • Scripts/ATUALIZA_PRECOVENDA.sql:7 - parâmetro I_PC_MARGEMVENDA NUMERIC(5,2).
  • Scripts/ATUALIZA_PRECOVENDA.sql:91, 152, 241 - IF (v_pc_margemtab IS NULL) THEN v_pc_margemtab = I_PC_MARGEMVENDA; (fallback final nos 3 métodos).
  • Scripts/ATUALIZA_PRECOVENDA.sql:244-282 - lógica dos métodos 1 e 2 (markdown divisor para ST_PRECOVENDA IN ('D','B','G'), markup para demais).
  • Scripts/ATUALIZA_PRECOVENDA.sql:335-336 - repasse recursivo para sub-itens.
  • Scripts/GERA_NOTAFISCAL.sql:86, 257, 264, 1114 - lê de PARMFATUR e chama ATUALIZA_PRECOVENDA.
  • Scripts/GERA_ESTOQUE_NOTAFISCAL.sql:88, 171, 176 - mesma leitura.
  • Scripts/GERA_ESTOQUE.sql:54, 712, 715, 730 - leitura + chamada de ATUALIZA_PRECOVENDA em entradas.
  • Scripts/RECALCULA_PRECOVENDA.sql:19, 31-34, 111, 117 - lê V_PC_MARGEMVENDA e repassa.
  • Scripts/RECALCULA_PRECOCOMPRA.sql:22, 35-38, 149-150 - fallback final: else if ( V_PC_MARGEMVENDA is not null ) then PC_MARGEM = V_PC_MARGEMVENDA;.
  • Scripts/RETORNA_CUSTOPRODUTO.sql:25, 32-35, 162-163 - mesma lógica de último fallback.
  • Scripts/VIEW_CNF006.sql:578-582 - COALESCE(I.PC_MARGEMLUCRO, P.PC_MARGEMVENDA) no cálculo de ICMS.

DDL​

  • docs/schema/tables/PARMFATUR.sql:41 - definição:
PC_MARGEMVENDA DOM_NUMERIC3_2,

DOM_NUMERIC3_2 = NUMERIC(3,2) → valor máximo 9,99. Note a divergência: a procedure ATUALIZA_PRECOVENDA declara seu parâmetro como NUMERIC(5,2) (até 999,99), mas o campo persistido no PARMFATUR fica limitado a 9,99. Margens acima disso devem ser configuradas em TABPRECO.PC_MARGEM ou ITEM.PC_MARGEMLUCRO.