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_MARGEMVENDATipo: Numérico (percentual %) -DOM_NUMERIC3_2Valor padrão:NULL(vazio - nenhum default é atribuído noAfterInsertdo 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ódulo | Código | Como usa PC_MARGEMVENDA |
|---|---|---|
| Parâmetros Faturamento | MFA001 | Cadastro do próprio valor - TDBEdit edtPC_MARGEMVENDA no grupo Opção 1 (UMFA001.dfm:3125-3141) |
| NF Entrada | MNF001 | Lê 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ço | MPD014 | Usa coluna computada PC_MARGEMVENDA no grid de formação de preço (é valor calculado, não lido deste parâmetro) |
| Custo Cadastro Fiscal | CFA001, CFA002 | Carrega iPC_MARGEMVENDA da PARMFATUR ao validar empresa |
| Análise Estoque | CEQ003, CEQ007 | Carrega iPC_MARGEMVENDA da PARMFATUR para uso em análises |
| Custo NF Complementar | CNF005 | Busca PC_MARGEMVENDA em dmCNF005.iQTMARGEM |
| Configuração Tributária | CNF017 | Grid/update inclui PC_MARGEMVENDA no SELECT/UPDATE de PARMFATUR |
| Configuração Pedido | CPD009 | Update de PARMFATUR inclui PC_MARGEMVENDA |
| Cadastro Produto | TPO001 | Lê PC_MARGEMVENDA em dmTPO001.iQTMARGEM ao abrir |
| Relatório Custo/Venda | RNF006 | Usa como fallback de PC_MARGEM em SELECT computado |
| Relatório NF Entrada | RNF026 | COALESCE(I.PC_MARGEMLUCRO, TP.PC_MARGEM, PF.PC_MARGEMVENDA) PC_MARGEM |
| Relatório Análise | RCA006 | Usa COALESCE(TI.PC_MARGEM, I.PC_MARGEMLUCRO, V.PC_MARGEM, PF.PC_MARGEMVENDA) PC_MARGEM |
Procedures impactadas
| Procedure | Arquivo | Uso |
|---|---|---|
ATUALIZA_PRECOVENDA | Scripts/ATUALIZA_PRECOVENDA.sql | Recebe 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_NOTAFISCAL | Scripts/GERA_NOTAFISCAL.sql | Lê P.PC_MARGEMVENDA de PARMFATUR em I_PC_MARGEMVENDA e repassa para ATUALIZA_PRECOVENDA na geração de nota |
GERA_ESTOQUE_NOTAFISCAL | Scripts/GERA_ESTOQUE_NOTAFISCAL.sql | Lê P.PC_MARGEMVENDA de PARMFATUR em I_PC_MARGEMVENDA para atualização de estoque/preço |
GERA_ESTOQUE | Scripts/GERA_ESTOQUE.sql | Em operação de entrada (I_TP_OPERACAO = 'E'), lê P.PC_MARGEMVENDA e repassa para ATUALIZA_PRECOVENDA |
RECALCULA_PRECOVENDA | Scripts/RECALCULA_PRECOVENDA.sql | Lê V_PC_MARGEMVENDA de PARMFATUR e repassa para ATUALIZA_PRECOVENDA no recálculo |
RECALCULA_PRECOCOMPRA | Scripts/RECALCULA_PRECOCOMPRA.sql | Fallback final em PC_MARGEM = V_PC_MARGEMVENDA quando margens mais específicas são nulas |
RETORNA_CUSTOPRODUTO | Scripts/RETORNA_CUSTOPRODUTO.sql | Retorna PC_MARGEM = V_PC_MARGEMVENDA como último fallback no cálculo do custo/margem do produto |
VIEW_CNF006 | Scripts/VIEW_CNF006.sql | Cálculo de ICMS fiscal: COALESCE(I.PC_MARGEMLUCRO, P.PC_MARGEMVENDA) |
Campos envolvidos
| Campo | Tabela | Descrição |
|---|---|---|
PC_MARGEMVENDA | PARMFATUR | Margem percentual padrão da empresa (este parâmetro) |
PC_MARGEMLUCRO | ITEM | Margem específica do produto (prioridade maior) |
PC_MARGEM | TABPRECO | Margem da tabela de preço (prioridade intermediária) |
PC_MARGEM | ITEMTABPRECO | Margem do item dentro de uma tabela específica (prioridade máxima) |
ST_PRECOVENDA | PARMFATUR | Define QUAL fórmula de cálculo usa a margem (veja abaixo) |
VL_UNITARIO | ITEMTABPRECO / ITEMNOTA | Preço unitário gerado a partir do custo aplicando a margem |
CD_TABPRECO | PARMFATUR | Tabela 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 acontece | Detalhe |
|---|---|
| Cadastro (MFA001) | AfterInsert não atribui default - campo nasce vazio |
| Ao ler no MNF001 | Se vazio, o sistema tenta buscar TABPRECO.PC_MARGEM da tabela configurada (CD_TABPRECO) e usa esse valor |
Ao passar na ATUALIZA_PRECOVENDA | Se 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ático | O 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
- Em MFA001 → Opção 1 →
% Margem Venda= vazio (em branco). - Certifique-se que a
CD_TABPRECOconfigurada também não temPC_MARGEM. - Certifique-se que o produto também não tem
PC_MARGEMLUCRO(TPO001). - Lance uma nota fiscal de entrada em MNF001 com um produto cujo custo subiu.
- 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_PRECOVENDA | Fó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,70Preco = 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áximo9.99, embora a procedureATUALIZA_PRECOVENDAdeclareNUMERIC(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
- Em MFA001 → Opção 1 →
% Margem Venda=5,00(permitido) eST_PRECOVENDA= qualquer método de recálculo. - Certifique-se que o produto X não tem
PC_MARGEMLUCRO(TPO001). - Certifique-se que a tabela de preço configurada não tem
PC_MARGEMnem registroITEMTABPRECOcom margem específica. - Lance uma entrada de NF em MNF001 do produto X com custo R$ 100,00.
- Ao confirmar a nota, o
GERA_NOTAFISCALchamaATUALIZA_PRECOVENDA(..., I_PC_MARGEMVENDA = 5,00, ...). - A procedure aplica a fórmula conforme
ST_PRECOVENDAe grava o novo preço emITEMTABPRECO.VL_PRECO. - 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: TDBEditcomDataField = 'PC_MARGEMVENDA', ligado admMFA001.dsPARMFATUR.source/MFA001/UMFA001.dfm:2407-2420- Labellbl15comCaption = '% Margem Venda',FocusControl = edtPC_MARGEMVENDA.source/MFA001/UMFA001.dfm:2421-2434- Labellbl30comCaption = '[MNF017]'apontando para o edit.source/MFA001/UMFA001.pas:239- declaraçãoedtPC_MARGEMVENDA: TDBEditno 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-...-tabPARMFATURAfterInsertNÃO atribui valor aPC_MARGEMVENDA(nasce NULL).
Delphi - uso como fallback em MNF001
source/MNF001/UdmMNF001.pas:1110- variável públicaiPC_MARGEMVENDA: String.source/MNF001/UdmMNF001.pas:1375, 1401-1406- leitura do parâmetro + fallback paraTABPRECO.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 paratabCUSTO.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_MARGEMVENDAemiPcMargeme passa paraATUALIZA_PRECOVENDA.
Delphi - demais módulos consumidores
source/CEQ003/UdmCEQ003.pas:68, 189, 208-iPC_MARGEMVENDAdeclarada/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- buscaPc_MargemVendada PARMFATUR ao validar empresa.source/CFA002/UdmCFA002.pas:142, 242, 261- mesma lógica.source/CNF005/UdmCNF005.pas:234-244- lêPC_MARGEMVENDAemdmCNF005.iQTMARGEM.source/CNF017/UdmCNF017.dfm:297, 443, 535- grid update/select do PARMFATUR incluiPC_MARGEMVENDA.source/CPD009/UdmCPD009.dfm:3046, 3192, 3284- update de PARMFATUR incluiPC_MARGEMVENDA.source/TPO001/UTPO001.pas:968-979- buscaPC_MARGEMVENDAemdmTPO001.iQTMARGEMno cadastro de produto.source/MPD002/UMPD002.pas:5366-PC_MARGEMVENDAcomo 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âmetroI_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 paraST_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 chamaATUALIZA_PRECOVENDA.Scripts/GERA_ESTOQUE_NOTAFISCAL.sql:88, 171, 176- mesma leitura.Scripts/GERA_ESTOQUE.sql:54, 712, 715, 730- leitura + chamada deATUALIZA_PRECOVENDAem entradas.Scripts/RECALCULA_PRECOVENDA.sql:19, 31-34, 111, 117- lêV_PC_MARGEMVENDAe 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.