PC_DESCONTOPED - Percentual Máximo de Desconto em Pedido
Tela: MFA001 - Parâmetros de Faturamento Localização: Parâmetros → Pedidos / O.S. → Opção 1 (rótulo no formulário: % Máx Desconto Pedido) Tabela:
PARMFATUR.PC_DESCONTOPEDTipo: Numérico (percentual %) —DOM_NUMERIC3_2no DDL;TBCDFieldcomPrecision=4 / Size=2no client (faixa prática: 0,00 a 99,99;DisplayFormat = '##0.00') Valor padrão:NULL(não preenchido noAfterInsertdeUdmMFA001.pas— equivale a "sem limite configurado para pedidos")
Telas impactadas
| Módulo | Código | Papel |
|---|---|---|
| Parâmetros de Faturamento | MFA001 | Produtora — cadastra/edita o valor |
| Pedido de Venda | MPD002 | Consumidora direta — inclui P.PC_DESCONTOPED no SELECT de BuscaParametros (o bloqueio efetivo é delegado à procedure VERIFICA_BLOQUEIO) |
| Orçamento | MPD004 | Consumidora direta — carrega iPC_DESCONTOPED da PARMFATUR para controle de desconto em orçamentos |
| Pedido (variante) | MPD020 | Consumidora direta — carrega iPC_DESCONTOPED em Resultado[20] da carga de parâmetros |
| Troca / Devolução | MPD043 | Consumidora direta — aplica COALESCE(ITB.PC_DESCONTOMAXIMO, P.PC_DESCONTOPED) como teto de desconto (fallback por item → parâmetro da empresa). Acrescenta +10% quando ST_PACOTEFORMATURA = 'S'. |
| Comprovante Recap | CPD009 | Lê no dataset de parâmetros (INSERT/UPDATE/SELECT do PARMFATUR) |
| Recapadora | RCA006 | Lê no dataset de parâmetros (INSERT/UPDATE/SELECT do PARMFATUR) |
Atenção — homônimos que NÃO são este parâmetro:
ITEMPEDIDO.PC_DESCONTOPEDIDO(campo em MPD097) → percentual de desconto por item do pedido, não o teto da empresa.PARMFATUR.PC_DESCONTOMAX→ limite para notas fiscais (ver PC_DESCONTOMAX). A proceduraVERIFICA_BLOQUEIOusaPC_DESCONTOMAXpara NFs ePC_DESCONTOPEDpara pedidos — são parâmetros distintos.
Procedures impactadas
| Procedure | Papel |
|---|---|
VERIFICA_BLOQUEIO | Consumidora central. Lê PARMFATUR.PC_DESCONTOPED junto com PC_DESCONTOMAX e, quando o documento é Pedido (I_TP_DOCTO = 'P'), Recapagem de pneu ('R') ou Ordem de Serviço/Orçamento ('O'), substitui V_PC_DESCONTOMAX pelo valor de V_PC_DESCONTOPED antes de comparar o desconto concedido. O bloqueio continua sendo do tipo 'W' quando o desconto ultrapassa o teto. |
Campos envolvidos
| Campo | Tabela | Descrição |
|---|---|---|
PC_DESCONTOPED | PARMFATUR | Percentual máximo de desconto para pedidos de venda, pedidos de recapagem (PEDIDOPNEU) e ordens de serviço / orçamentos |
PC_DESCONTOMAX | PARMFATUR | Percentual máximo para notas fiscais (troca feita pela procedure conforme I_TP_DOCTO) |
ST_BLOQUEIOPED | PARMFATUR | Liga/desliga o bloqueio em pedidos — precisa estar em um status que ative a checagem ('Q', 'A', 'O', 'W', etc.) |
VL_DESCONTO / VL_TOTPRODUTO | PEDIDO / PEDIDOPNEU / ORDEMSERVICO | Base de cálculo usada em VERIFICA_BLOQUEIO para obter V_PC_DESC |
PC_DESCONTOMAXIMO | ITEMTABPRECO | Limite por item — quando preenchido, tem prioridade sobre PC_DESCONTOPED em MPD043 (COALESCE(ITB.PC_DESCONTOMAXIMO, P.PC_DESCONTOPED)) e em ramo específico de VERIFICA_BLOQUEIO |
ST_PACOTEFORMATURA | TROCA | Em MPD043, quando 'S' soma +10% ao PC_DESCONTOPED (pacote de formatura) |
Comportamento / Fórmula de aplicação
O parâmetro representa o percentual máximo de desconto permitido no total de pedidos / recapagens / ordens de serviço. Toda a lógica central está na procedure VERIFICA_BLOQUEIO (Scripts/VERIFICA_BLOQUEIO.sql). Diferente de PC_DESCONTOMAX (que é o teto de NF), este campo só entra em cena quando o documento é não-nota:
-- Leitura conjunta (linhas 143-152 de VERIFICA_BLOQUEIO.sql)
SELECT ST_BLOQUEIONF, ST_BLOQUEIOPED, PC_DESCONTOMAX, PC_DESCONTOPED, ...
FROM PARMFATUR
WHERE CD_EMPRESA = :I_CD_EMPRESA
INTO :V_ST_BLOQUEIONF, :V_ST_BLOQUEIOPED, :V_PC_DESCONTONF, :V_PC_DESCONTOPED, ...;
-- Pedido de venda (linha 172-174)
IF ( I_TP_DOCTO = 'P' ) THEN BEGIN
V_ST_BLOQUEIO = V_ST_BLOQUEIOPED;
V_PC_DESCONTOMAX = V_PC_DESCONTOPED; -- troca o teto
END
-- Pedido de recapagem de pneu (linha 275-278)
IF ( I_TP_DOCTO = 'R' ) THEN BEGIN
V_ST_BLOQUEIO = V_ST_BLOQUEIOPED;
V_PC_DESCONTOMAX = V_PC_DESCONTOPED;
END
-- Ordem de Serviço / Orçamento (linhas 352-356)
IF (I_TP_DOCTO = 'S') THEN V_ST_BLOQUEIO = V_TP_BLOQUEIOOS;
IF (I_TP_DOCTO = 'O') THEN V_ST_BLOQUEIO = V_ST_BLOQUEIOPED;
V_PC_DESCONTOMAX = V_PC_DESCONTOPED;
A partir daí, a mesma faixa de bloqueio usada para NF é reaproveitada — só que com o valor de PC_DESCONTOPED:
-- Faixa principal de comparação (linhas 1096-1106)
IF ( V_PC_DESCONTOMAX IS NOT NULL ) THEN BEGIN
V_PC_DESC = (COALESCE(V_VL_DESCONTO,0) * 100) / nullif(V_VL_TOTPRODUTO,0);
IF ( V_PC_DESC > V_PC_DESCONTOMAX ) THEN BEGIN
V_TP_BLOQUEIO = V_TP_BLOQUEIO || 'W';
V_DS_BLOQUEIO = V_DS_BLOQUEIO ||
'O Percentual de Desconto está acima do Máximo Permitido. ' ||
'Desconto Concedido(%).: ' || REPLACE(V_PC_DESC,'.',',') || '. ' ||
'Desconto Permitido(%).: ' || REPLACE(V_PC_DESCONTOMAX,'.',',');
END
END
Fórmula:
PC_DESC_CONCEDIDO = (VL_DESCONTO × 100) / VL_TOTPRODUTO. Se o resultado for maior quePC_DESCONTOPED(após a trocaV_PC_DESCONTOMAX := V_PC_DESCONTOPED), dispara bloqueio do tipo'W'com a mesma mensagem usada para nota.
Uso específico em Troca/Devolução — MPD043
MPD043 faz a própria checagem em Delphi (não delega a VERIFICA_BLOQUEIO):
// source/MPD043/UMPD043.pas:961-965 — busca com fallback por item
Consulta := ' SELECT COALESCE(ITB.PC_DESCONTOMAXIMO, P.PC_DESCONTOPED) ' +
' FROM PARMFATUR P ' +
' LEFT JOIN ITEMTABPRECO ITB ON (ITB.CD_TABPRECO = ' + Resultado[0] +
' AND ITB.CD_ITEM = ' + dmMPD043.tabITEMCD_ITEM.AsString + ')' +
' WHERE P.CD_EMPRESA = ' + IntToStr(sessao.empresa.cd_empresa);
// source/MPD043/UMPD043.pas:3355-3362 — validação do desconto na troca
if ( vl_desconto > 0 ) then begin
Resultado := ExecutaConsulta(dmMPD043.transaction,
'SELECT COALESCE(P.PC_DESCONTOPED,0) FROM PARMFATUR P WHERE P.CD_EMPRESA = '
+ IntToStr(sessao.empresa.cd_empresa));
vl_final := ((vl_desconto*100) / Vl_final);
Vl_final := RoundTo(Vl_final,-2);
if (dmMPD043.tabTROCAST_PACOTEFORMATURA.AsString = 'S') then begin
Resultado[0] := FloatToStr(StrToFloat(Resultado[0]) + 10); // pacote de formatura: +10%
end;
Ou seja, em troca de formatura o teto efetivo é PC_DESCONTOPED + 10.
Valor = NULL (padrão ao criar o registro no MFA001)
| Aspecto | Comportamento |
|---|---|
| Precisa estar preenchido? | Não — é o estado inicial (o AfterInsert de UdmMFA001.pas não atribui valor) |
Bloqueio em VERIFICA_BLOQUEIO | Não ocorre para pedidos — após a troca V_PC_DESCONTOMAX := V_PC_DESCONTOPED, a guarda IF (V_PC_DESCONTOMAX IS NOT NULL) THEN ... (linha 1096) pula a checagem |
| MPD043 | COALESCE(P.PC_DESCONTOPED, 0) faz o NULL virar 0, o que equivale a proibir desconto (ver comportamento abaixo) — esse é um ponto de atenção: o padrão da empresa difere entre fluxos |
| Fallback por item (MPD043) | Se ITEMTABPRECO.PC_DESCONTOMAXIMO estiver preenchido para o produto, o COALESCE usa esse limite antes do parâmetro da empresa |
Resultado esperado: no fluxo geral de pedidos (VERIFICA_BLOQUEIO), o sistema não impõe teto. Em MPD043, porém, o COALESCE(...,0) torna o valor NULL equivalente a 0 — qualquer desconto concedido é bloqueado.
Valor = 0
| Aspecto | Comportamento |
|---|---|
Bloqueio em VERIFICA_BLOQUEIO | Zero desconto permitido em pedidos. A guarda IS NOT NULL passa e a comparação V_PC_DESC > 0 bloqueia qualquer desconto positivo |
| MPD043 | Mesma lógica — qualquer vl_desconto > 0 excede o teto |
| Validação no próprio MFA001 | Não existe OnValidate para este campo (diferente de PC_DESCONTOMAX, que rejeita negativos). Ou seja, é possível gravar 0 e até valores negativos sem mensagem — a proteção só vem do tipo NUMERIC(3,2), que exige valor ≥ 0 na sintaxe |
Resultado esperado: equivale a proibir descontos em pedidos (exceto se o item tiver limite próprio via ITEMTABPRECO.PC_DESCONTOMAXIMO).
Valor > 0 (ex.: 5,00)
| Aspecto | Comportamento |
|---|---|
| Teto aceito sem bloqueio | VL_DESCONTO / VL_TOTPRODUTO × 100 ≤ PC_DESCONTOPED |
| Acima do teto | Bloqueio 'W' com mensagem "O Percentual de Desconto está acima do Máximo Permitido. Desconto Concedido(%).: X. Desconto Permitido(%).: Y." |
| Origem do bloqueio | Procedure VERIFICA_BLOQUEIO (saída em O_TP_BLOQUEIO/O_DS_BLOQUEIO) consumida pelas telas MPD002, MPD020, MPD011 etc. no salvamento/fechamento do pedido — ou validação direta em MPD043 |
Simulação passo a passo
- MFA001 → aba Parâmetros → Pedidos / O.S. → Opção 1 → campo % Máx Desconto Pedido =
5,00. - Aba Parâmetros → Faturamento → Opção 1 → campo % Máx Desconto Nota (PC_DESCONTOMAX) =
10,00(para enxergar a bifurcação). ST_BLOQUEIOPEDprecisa estar em um status que ative a checagem de desconto (ex.:'O'ou'W').- Salve os parâmetros (F6).
- Emita um pedido (MPD002) com total de produtos
VL_TOTPRODUTO = R$ 1.000,00:- Desconto R$ 40,00 (4%) →
V_PC_DESC = 4 ≤ 5→ salva normalmente. - Desconto R$ 80,00 (8%) →
V_PC_DESC = 8 > 5→ bloqueia o pedido com:O Percentual de Desconto está acima do Máximo Permitido. Desconto Concedido(%).: 8,00. Desconto Permitido(%).: 5,00
- Desconto R$ 40,00 (4%) →
- Converta o mesmo pedido em NF (MNF002) com o mesmo desconto (8%):
- Agora
I_TP_DOCTO = 'N'→ a procedure não trocaV_PC_DESCONTOMAXpeloPC_DESCONTOPED; usa o limite de NF (10,00). V_PC_DESC = 8 ≤ 10→ NF salva normalmente.
- Agora
Resultado esperado: o mesmo desconto (8%) que é bloqueado no pedido passa sem bloqueio na NF. Essa é a razão de existência do parâmetro: permitir políticas diferentes para pedido e nota (tipicamente pedido mais restrito, NF mais permissiva ou vice-versa).
Simulação em troca de formatura (MPD043)
PC_DESCONTOPED = 5,00.- Troca com
ST_PACOTEFORMATURA = 'S'evl_desconto = 12%deVl_final:- Teto efetivo =
5 + 10 = 15. → permite.
- Teto efetivo =
- Mesma troca com
ST_PACOTEFORMATURA = 'N':- Teto efetivo =
5. → bloqueia.
- Teto efetivo =
Interação com outros parâmetros
| Parâmetro | Efeito combinado |
|---|---|
PARMFATUR.PC_DESCONTOMAX | Complementar. PC_DESCONTOPED é o teto de pedido/recapagem/OS; PC_DESCONTOMAX é o teto de NF. A procedure VERIFICA_BLOQUEIO escolhe um dos dois conforme I_TP_DOCTO ('N' → PC_DESCONTOMAX; 'P'/'R'/'O' → PC_DESCONTOPED). |
PARMFATUR.ST_BLOQUEIOPED | Habilita a checagem. Sem um status que ative a comparação de desconto ('Q', 'A', 'O', 'W', etc.), PC_DESCONTOPED é lido mas nunca testado — a procedure nem entra no ramo. |
ITEMTABPRECO.PC_DESCONTOMAXIMO | Prioridade por item. Em MPD043 o COALESCE(ITB.PC_DESCONTOMAXIMO, P.PC_DESCONTOPED) faz o limite por item prevalecer; em VERIFICA_BLOQUEIO o ramo V_PC_DESCONTOMAXIMOPRODUTO IS NOT NULL também tem precedência (bloqueio 'E'). |
PARMDESCONTO.PC_DESCONTO (faixa por faturamento) | Teto adicional via faixa de cliente. Em VERIFICA_BLOQUEIO a variável V_PC_DESCONTOPED é reutilizada (linhas 1150-1167) para guardar o % de desconto da faixa de faturamento médio — se o desconto concedido ultrapassa a faixa, dispara bloqueio 'Y'. Isso é independente do parâmetro PARMFATUR.PC_DESCONTOPED, mas compartilha o mesmo nome de variável interna. |
TROCA.ST_PACOTEFORMATURA (MPD043) | Quando 'S', soma +10% ao teto efetivo (PC_DESCONTOPED + 10). |
PARMUSUARIO.PC_DESCONTOMAX (ADM012) | Limite por usuário aplicado em outras procedures/módulos — não substitui nem participa diretamente desta checagem em pedidos (atua em fluxos financeiros). |
Sem OnValidate no MFA001 | Diferente de PC_DESCONTOMAX (que tem tabPARMFATURPC_DESCONTOMAXValidate rejeitando valor < 0), PC_DESCONTOPED não tem validação em tela — confia apenas no tipo NUMERIC(3,2) do Firebird. |
Referências no Código Fonte
Delphi
| Arquivo | Linhas | Papel |
|---|---|---|
source/MFA001/UMFA001.dfm | 7846-7858, 8545-8561 | Label lbl36 = '% Máx Desconto Pedido' (pai: pagPedidoOp1 → GroupBox "Parâmetros de Pedidos/ Ordem de Serviço") e TDBEdit edtPC_DESCONTOPED (DataField=PC_DESCONTOPED) |
source/MFA001/UMFA001.pas | 308 | Declaração de edtPC_DESCONTOPED: TDBEdit |
source/MFA001/UdmMFA001.dfm | 103, 907-913, 2355, 2504, 2695, 2983 | Field TBCDField (Precision=4, Size=2, DisplayFormat='##0.00'); cláusulas SELECT/INSERT/UPDATE do PARMFATUR incluindo PC_DESCONTOPED |
source/MFA001/UdmMFA001.pas | 90 | Declaração do field tabPARMFATURPC_DESCONTOPED: TBCDField. Nenhum OnValidate nem atribuição de padrão em AfterInsert. |
source/MPD002/UdmMPD002.pas | 5740 | BuscaParametros inclui P.PC_DESCONTOPED no SELECT (posição 22 do array de resultados) |
source/MPD004/UdmMPD004.pas | 315, 372, 389 | Declara iPC_DESCONTOPED: String; SELECT de PARMFATUR; atribui iPC_DESCONTOPED := Resultado[12] no carregamento do orçamento |
source/MPD020/UdmMPD020.pas | 239, 321, 357 | Declara iPC_DESCONTOPED: String; SELECT de PARMFATUR; atribui iPC_DESCONTOPED := Resultado[20] |
source/MPD043/UMPD043.pas | 961-965, 3355-3362 | Consumo direto — usa COALESCE(ITB.PC_DESCONTOMAXIMO, P.PC_DESCONTOPED) para o teto por item, e COALESCE(P.PC_DESCONTOPED, 0) no bloqueio final (com +10 para pacote de formatura) |
source/CPD009/UdmCPD009.dfm | 360, 441, 557 | Leitura no dataset de parâmetros (INSERT/UPDATE/SELECT de PARMFATUR) |
source/RCA006/UdmRCA006.dfm | 3109, 3190, 3306 | Leitura no dataset de parâmetros (INSERT/UPDATE/SELECT de PARMFATUR) |
SQL (Firebird)
| Arquivo | Linhas | Papel |
|---|---|---|
Scripts/VERIFICA_BLOQUEIO.sql | 23, 143-152, 172-174, 277-278, 356, 1096-1106, 1150-1167 | Procedure central. Lê PC_DESCONTOPED em conjunto com PC_DESCONTOMAX e, para I_TP_DOCTO em {'P','R','O'}, substitui o teto (V_PC_DESCONTOMAX := V_PC_DESCONTOPED). Aplica bloqueio 'W' quando o % concedido ultrapassa. A mesma variável interna V_PC_DESCONTOPED é reutilizada (linhas 1150-1167) para o teto por faixa de faturamento (PARMDESCONTO), gerando bloqueio 'Y'. |
docs/schema/tables/PARMFATUR.sql | 47 | DDL: PC_DESCONTOPED DOM_NUMERIC3_2 |