PC_DESCONTOMAX - Percentual Máximo de Desconto (Nota/Pedido)
Tela: MFA001 - Parâmetros de Faturamento Localização: Parâmetros → Notas Fiscais → Parâmetros de Notas (rótulo no formulário: % Máx Desconto Nota) Tabela:
PARMFATUR.PC_DESCONTOMAXTipo: Numérico (percentual %) —DOM_NUMERIC3_2no DDL;TBCDFieldcomPrecision=4 / Size=2no client (faixa prática: 0,00 a 99,99) Valor padrão:NULL(não preenchido noAfterInsert— equivale a "sem limite configurado")
Telas impactadas
| Módulo | Código | Papel |
|---|---|---|
| Parâmetros de Faturamento | MFA001 | Produtora — cadastra/edita o valor |
| NF Saída | MNF002 | Lê o parâmetro em BuscaParametros_MNF002 (o bloqueio real é delegado à procedure VERIFICA_BLOQUEIO) |
| NF Saída Simplificada | MNF017 | Consumidora direta — valida em iPC_DESCONTOMAX contra VL_DESCONTO do cabeçalho |
| Cupom Fiscal | MNF008 | Lê em iPC_DESCONTOMAX |
| Pedido via Tablet/Coleta | MPD011 | Lê em PF.PC_DESCONTOMAX |
| Visita (orçamento rápido) | TFA018 | Lê em PC_DESCONTO para controlar desconto da visita |
| Caixa | MCO006 | Lê o parâmetro junto com os demais do faturamento |
| Comprovante Recap | CPD009 | Lê no dataset de parâmetros |
| Recapadora | RCA006 | Lê no dataset de parâmetros |
Atenção — homônimos que NÃO são este parâmetro:
PARMUSUARIO.PC_DESCONTOMAX(tela ADM012, usada em MFC004, OFI001 e na procedureVALIDA_BLOQDESCMAXSUBGRUPO) → limite por usuário.PARMORCAMENTO.PC_DESCONTOMAX(tela MFA003, consumida em MPD004/MPD044) → limite de desconto de orçamentos.ITEMTABPRECO.PC_DESCONTOMAXIMO(tela TFA006) → limite de desconto por item/tabela de preço.
Procedures impactadas
| Procedure | Papel |
|---|---|
VERIFICA_BLOQUEIO | Consumidora principal. Lê PARMFATUR.PC_DESCONTOMAX e PARMFATUR.PC_DESCONTOPED e aplica os bloqueios 'W' (desconto acima do máximo) e 'Q' (valor líquido abaixo do permitido) quando ST_BLOQUEIONF/ST_BLOQUEIOPED estão ativos. |
Campos envolvidos
| Campo | Tabela | Descrição |
|---|---|---|
PC_DESCONTOMAX | PARMFATUR | Percentual máximo de desconto para notas fiscais (documento = 'N') |
PC_DESCONTOPED | PARMFATUR | Percentual máximo de desconto para pedidos (documento = 'P') — é usado no lugar de PC_DESCONTOMAX quando I_TP_DOCTO = 'P' |
ST_BLOQUEIONF | PARMFATUR | Liga/desliga o bloqueio em notas (valores 'Q', 'A', 'O', 'W' ativam a checagem de desconto) |
ST_BLOQUEIOPED | PARMFATUR | Equivalente para pedidos |
VL_DESCONTO / PC_DESCONTO | NOTA / PEDIDO / ITEMNOTA | Valor/percentual de desconto concedido (é o que é comparado) |
VL_TOTPRODUTO | NOTA / PEDIDO | Base de cálculo usada em VERIFICA_BLOQUEIO para obter o V_PC_DESC |
PC_DESCONTOMAXIMO | ITEMTABPRECO | Limite por item (quando presente, tem prioridade sobre PC_DESCONTOMAX em algumas ramificações da procedure) |
PC_DESCONTOMAX | PARMUSUARIO | Limite por usuário (parâmetro diferente, usado em financeiro / fechamento) |
Comportamento / Fórmula de aplicação
O parâmetro representa o percentual máximo de desconto permitido no total da nota/pedido. A checagem central é feita pela procedure VERIFICA_BLOQUEIO (Scripts/VERIFICA_BLOQUEIO.sql), que lê o campo em conjunto com ST_BLOQUEIONF / ST_BLOQUEIOPED:
-- Leitura (linhas 143-149 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, ...;
-- Se o documento é Pedido, usa PC_DESCONTOPED no lugar (linha 174)
IF ( I_TP_DOCTO = 'P' ) THEN BEGIN
V_ST_BLOQUEIO = V_ST_BLOQUEIOPED;
V_PC_DESCONTOMAX = V_PC_DESCONTOPED;
A fórmula do percentual concedido, usada na faixa principal de bloqueio (linhas 1096-1106):
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 = 'O Percentual de Desconto está acima do Máximo Permitido. ' ||
'Desconto Concedido(%).: ' || V_PC_DESC || '. ' ||
'Desconto Permitido(%).: ' || V_PC_DESCONTOMAX;
END
Fórmula:
PC_DESC_CONCEDIDO = (VL_DESCONTO × 100) / VL_TOTPRODUTO. Se o resultado for maior quePC_DESCONTOMAX, dispara bloqueio do tipo'W'(ou'Q', na checagem de valor líquido).
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 — a guarda IF (V_PC_DESCONTOMAX IS NOT NULL) THEN ... (linha 1096) pula a checagem |
| Bloqueio em MNF017 | Não ocorre — if (Trim(dmMNF017.iPC_DESCONTOMAX) <> '') then ... (linha 1397) pula |
| Fallback por item | Se ITEMTABPRECO.PC_DESCONTOMAXIMO estiver preenchido para o produto, a procedure usa o limite do item (ramo V_PC_DESCONTOMAXIMOPRODUTO) |
Resultado esperado: o sistema não impõe teto de desconto pelo parâmetro da empresa. Só haverá bloqueio se o item tiver limite próprio (ITEMTABPRECO.PC_DESCONTOMAXIMO) ou se o usuário tiver limite em PARMUSUARIO.PC_DESCONTOMAX.
Valor = 0
| Aspecto | Comportamento |
|---|---|
Validação em tabPARMFATURPC_DESCONTOMAXValidate | Aceita (regra é if AsFloat < 0, 0 passa) |
Bloqueio em VERIFICA_BLOQUEIO | Zero desconto permitido. A guarda IS NOT NULL passa e a comparação V_PC_DESC > 0 bloqueia qualquer desconto positivo |
| Bloqueio em MNF017 | Mesma lógica — qualquer VL_DESCONTO > 0 dispara a mensagem "O Percentual de Desconto está acima do Máximo Permitido." |
Resultado esperado: equivale a proibir descontos (exceto se houver autorizador ou limite mais permissivo por item). Essa é a diferença fundamental entre NULL (sem limite) e 0 (zero de tolerância).
Valor > 0 (ex.: 10,00)
| Aspecto | Comportamento |
|---|---|
| Teto aceito sem bloqueio | VL_DESCONTO / VL_TOTPRODUTO × 100 ≤ PC_DESCONTOMAX |
| Acima do teto | Bloqueio 'W' (ou 'Q' se a checagem for via valor líquido vs tabela) 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 no fluxo de salvamento |
Simulação passo a passo
- MFA001 → aba Ambos → Opção 1 → campo % Máx Desconto Nota =
10,00(PC_DESCONTOMAX). - Para que a checagem ocorra em NF, o
ST_BLOQUEIONFprecisa estar em um status que ative o teste — a procedure considera descontos em('Q','A','O','W'...). AjusteST_BLOQUEIONFconforme o fluxo desejado. - Salve os parâmetros (F6).
- Emita uma NF (MNF002 ou MNF017) com total de produtos
VL_TOTPRODUTO = R$ 1.000,00. - Conceda R$ 80,00 de desconto (8%). →
V_PC_DESC = 8 ≤ 10→ salva normalmente. - Conceda R$ 150,00 de desconto (15%). →
V_PC_DESC = 15 > 10→ bloqueia com mensagem:O Percentual de Desconto está acima do Máximo Permitido. Desconto Concedido(%).: 15,00. Desconto Permitido(%).: 10,00
Resultado esperado: o fechamento/salvamento do documento é barrado quando o desconto total ultrapassa o percentual configurado.
Regra Geral / Interação com outros parâmetros
- Pedido vs. Nota: em pedidos (
I_TP_DOCTO = 'P'),VERIFICA_BLOQUEIOtroca o teto paraPC_DESCONTOPED. Ou seja,PC_DESCONTOMAXé, na prática, o limite de NFs;PC_DESCONTOPEDé o limite de pedidos. - ITEMTABPRECO.PC_DESCONTOMAXIMO tem prioridade por item: quando o produto possui limite próprio em sua tabela de preço (
V_PC_DESCONTOMAXIMOPRODUTO IS NOT NULL), a procedure usa esse limite em vez doPC_DESCONTOMAXda empresa (linhas 1083-1094 deVERIFICA_BLOQUEIO.sql). - PARMUSUARIO.PC_DESCONTOMAX (ADM012) é um limite adicional e independente por usuário, aplicado em outras procedures (
VALIDA_BLOQDESCMAXSUBGRUPO) e nos módulos financeiros (MFC004, OFI001). Não substitui este parâmetro. - Validação no próprio MFA001 (
UdmMFA001.pas:1176-1180): impede gravar valor negativo — mensagem"O Percentual deve ser Maior ou Igual a Zero!". Não há limite superior implícito (99,99 pelo tipo do campo). ST_BLOQUEIONF/ST_BLOQUEIOPEDprecisam estar ativos para que a procedure sequer entre nos ramos que comparam o desconto — sem eles,PC_DESCONTOMAXé preenchido, mas não é testado.- Comportamento especial em MNF017: o limite é comparado contra
tabCABECALHOVL_DESCONTO.AsFloat(o valor de desconto, não o percentual), o que é um ponto de atenção histórico — efetivamente só funciona como esperado quando o desconto já é expresso em percentual pela tela.
Referências no Código Fonte
Delphi
| Arquivo | Linhas | Papel |
|---|---|---|
source/MFA001/UMFA001.dfm | 5995-6645 | Label '% Máx Desconto Nota' e TDBEdit edtPC_DESCONTOMAX (DataField=PC_DESCONTOMAX) |
source/MFA001/UMFA001.pas | 379 | Declaração do edtPC_DESCONTOMAX: TDBEdit |
source/MFA001/UdmMFA001.dfm | 86, 753-760, 2353, 2504, 2694, 2966 | Field TBCDField (Precision=4, Size=2, DisplayFormat='##0.00'), cláusulas SELECT/INSERT/UPDATE do PARMFATUR |
source/MFA001/UdmMFA001.pas | 60, 366, 1176-1180 | Declaração do field, assinatura e corpo do OnValidate (rejeita valor < 0) |
source/MNF002/UdmMNF002.pas | 10492 | BuscaParametros_MNF002 inclui P.PC_DESCONTOMAX no SELECT |
source/MNF008/UdmMNF008.pas | 475, 652, 674, 757 | Declara iPC_DESCONTOMAX e popula via SELECT em PARMFATUR |
source/MNF017/UMNF017.pas | 161, 185 | Carrega dmMNF017.iPC_DESCONTOMAX |
source/MNF017/UdmMNF017.pas | 274, 1397-1405 | Consumo direto — bloqueia emissão com mensagem quando VL_DESCONTO > iPC_DESCONTOMAX |
source/MPD011/UdmMPD011.pas | 1579 | SELECT de PF.PC_DESCONTOMAX no carregamento de parâmetros |
source/TFA018/UTFA018.pas | 173-181 | SELECT e uso em PC_DESCONTO (variável global da visita) |
source/MCO006/UdmMCO006.pas | 2101 | Leitura junto com demais parâmetros de PARMFATUR |
source/CPD009/UdmCPD009.dfm | 540 | Leitura para comprovante recap |
source/RCA006/UdmRCA006.dfm | 3289 | Leitura no dataset de parâmetros |
SQL (Firebird)
| Arquivo | Linhas | Papel |
|---|---|---|
Scripts/VERIFICA_BLOQUEIO.sql | 24, 143-149, 174, 278, 356, 464, 679, 1019, 1042-1047, 1079, 1096-1106, 1187 | Procedure central de validação. Lê PC_DESCONTOMAX / PC_DESCONTOPED e aplica os bloqueios tipo 'W' (desconto acima do máximo) e 'Q' (valor líquido abaixo do permitido). |
docs/schema/tables/PARMFATUR.sql | 43 | DDL: PC_DESCONTOMAX DOM_NUMERIC3_2 |
Parâmetros homônimos (outros módulos — NÃO confundir)
| Arquivo | Campo | Contexto |
|---|---|---|
source/ADM012/UdmADM012.pas / .dfm | PARMUSUARIO.PC_DESCONTOMAX | Limite por usuário (financeiro) |
source/MFC004/UdmMFC004.pas | PARMUSUARIO.PC_DESCONTOMAX | Bloqueio de desconto em contas a receber/pagar |
source/OFI001/UdmOFI001.pas | PARMUSUARIO.PC_DESCONTOMAX | Bloqueio em ordem de serviço |
source/MFA003/UdmMFA003.* | PARMORCAMENTO.PC_DESCONTOMAX | Limite de orçamento |
source/MPD004/UdmMPD004.pas / source/MPD044/UdmMPD044.pas | PARMORCAMENTO.PC_DESCONTOMAX | Orçamento de venda / produção |
source/TFA006/UdmTFA006.* | ITEMTABPRECO.PC_DESCONTOMAXIMO | Limite por item na tabela de preço |
Scripts/VALIDA_BLOQDESCMAXSUBGRUPO.sql | PARMUSUARIO.PC_DESCONTOMAX | Validação de desconto máximo por subgrupo/usuário |