Parâmetro de Bloqueio de Estoque Negativo
Tela de configuração: MFA001 - Parâmetros de Faturamento Localização: Parâmetros → Ambos → Opção 1 Tabela:
PARMFATUR.ST_ESTOQUENEGATIVOValor padrão:N(Não) — definido emUdmMFA001.pas:485
Este parâmetro bloqueia a operação quando o item ficaria com estoque negativo. Diferente de ST_ALERTAESTOQUENEGATIVO, que apenas avisa o usuário, o ST_ESTOQUENEGATIVO = 'S' impede a gravação do item (lança exceção JException).
Telas impactadas
| Módulo | Código | Uso |
|---|---|---|
| Pedido de Venda | MPD002 | Bloqueia inclusão de item via VERIFICA_ESTOQUENEGATIVOPEDIDO (UMPD002.pas:6664); força parâmetro S em RETORNA_QTDEESTOQUEGRADE (UdmMPD002.pas:1143); valida ao salvar (UdmMPD002.pas:4268, UdmMPD002.pas:5938, 5972); checa ITEMLOCAL.ST_ESTOQUE antes de validar (UMPD002.pas:2185) |
| Pedido Mobile/Simplificado | MPD020 | Lê parâmetro em iST_ESTOQUENEGATIVO (UdmMPD020.pas:366); força Parametros[8] := 'S' na grade (UdmMPD020.pas:657); distingue bloqueio vs alerta (UdmMPD020.pas:955) |
| Orçamento | MPD018 | Lê em iST_ESTOQUENEGATIVO (UdmMPD018.pas:309); valida saldo em máquinas quando 'S' (UMPD018.pas:1217) |
| Pedido de Compra | MPD092 | Lê o parâmetro no SELECT da PARMFATUR |
| Pedido (Apoio) | MPD005 | Propaga para verificação de estoque |
| NF Saída (Outra) / Confirmação | MNF017 | Lê em iST_ESTOQUENEGATIVO (UMNF017.pas:198); força ParamGrade[8] := 'S' ao aplicar saldo na grade (UdmMNF017.pas:1225) |
| Nota Fiscal Saída | MNF002 | Carrega o campo no SELECT do PARMFATUR |
| NF Saída (Compra) | MNF007 | Carrega o campo no SELECT do PARMFATUR |
| NF Entrada (Avulsa) | MNF008 | Carrega o campo no SELECT do PARMFATUR |
| NF Devolução Compra | MNF026 | Carrega o campo no SELECT do PARMFATUR |
| Ordem de Serviço | MOF001 | Lê em iST_ESTOQUENEGATIVO (UdmMOF001.pas:753); valida saldo de peças utilizadas quando 'S' (UdmMOF001.pas:3055) |
| Ordem de Serviço (Outra) | MOF002 | Carrega o parâmetro do PARMFATUR |
| Contas a Receber | MCO006 | Apenas no SELECT do PARMFATUR (sem uso direto encontrado) |
| Consulta Pedidos | CPD009 | Inclui o campo no UPDATE/SELECT do PARMFATUR |
| Cadastro Auxiliar | RCA006 | Inclui o campo no UPDATE/SELECT do PARMFATUR |
| jGradeProduto (shared) | jGrade.pas | Recebe Parametros[8] = 'S' (flag "Valida apenas itens da grade com saldo") repassada pelas telas de venda |
Procedures impactadas
| Procedure | Arquivo | Uso |
|---|---|---|
VERIFICA_ESTOQUENEGATIVOPEDIDO | Scripts/VERIFICA_ESTOQUENEGATIVOPEDIDO.sql | Lê ST_ESTOQUENEGATIVO (linha 18, 29–32). Quando 'S', retorna O_ST_ALERTABLOQUEIA = 'B' (bloqueio) em vez de 'A' (alerta). Entra no IF principal quando ST_ALERTAESTOQUENEGATIVO <> 'N' OU ST_ESTOQUENEGATIVO <> 'N' (linhas 44–45). |
VERIFICA_ESTOQUENEGATIVONOTA | Scripts/VERIFICA_ESTOQUENEGATIVONOTA.sql | Mesmo padrão: decide entre 'B' (bloqueia) e 'A' (alerta) conforme ST_ESTOQUENEGATIVO. |
VERIFICA_ESTOQUENEGATIVOOS | Scripts/VERIFICA_ESTOQUENEGATIVOOS.sql | Carrega ST_ESTOQUENEGATIVO em I_BLOQUEIA (linhas 27–32) e usa para definir O_ST_ALERTABLOQUEIA. |
RETORNA_QTDEESTOQUEGRADE | Scripts/RETORNA_QTDEESTOQUEGRADE.sql | Lê ST_ESTOQUENEGATIVO em V_ST_ESTOQUENEGATIVO (linha 31). Quando ST_ALERTAESTOQUENEGATIVO = 'N' mas ST_ESTOQUENEGATIVO = 'S', ainda filtra somente grades com saldo (linhas 43–47). |
Campos envolvidos
| Campo | Descrição |
|---|---|
PARMFATUR.ST_ESTOQUENEGATIVO | Flag (S/N) que bloqueia operações com estoque negativo |
PARMFATUR.ST_ALERTAESTOQUENEGATIVO | Flag complementar (F/S/N) que apenas alerta (ver doc) |
ITEMPEDIDO.CD_OPERACAO | Operação de movimentação do item. Parâmetro só age quando preenchido |
ITEMLOCAL.ST_ESTOQUE | Em MPD002, consulta se o item controla estoque no local antes de validar (UMPD002.pas:2188) |
MOVIMENTACAO.ST_ESTOQUENEGATIVO, MOVIMENTACAO.TP_ESTOQUE | Definem se a operação efetivamente baixa estoque (flag flagEstoqueNegativo interna) |
Retorno O_ST_ALERTABLOQUEIA | B = Bloqueia / A = Alerta / N = OK — definido em VERIFICA_ESTOQUENEGATIVOPEDIDO.sql:173–179 |
Opções disponíveis
ComboBox
cmbST_ESTOQUENEGATIVO(UMFA001.dfm:3270–3296) com apenas duas opções:Items.Strings = ('Sim'#9'S', 'Não'#9'N')
S - Sim (Bloqueia)
| O que faz | Detalhe |
|---|---|
| Permite salvar com estoque negativo? | Não — lança JException.Create('W-0000', ...) e aborta a gravação |
| Onde bloqueia no Delphi | MPD002 UMPD002.pas:6664–6698 executa VERIFICA_ESTOQUENEGATIVOPEDIDO; se retornar 'B' levanta exceção |
| Onde bloqueia no SQL | VERIFICA_ESTOQUENEGATIVOPEDIDO.sql:173–175, VERIFICA_ESTOQUENEGATIVONOTA.sql, VERIFICA_ESTOQUENEGATIVOOS.sql definem O_ST_ALERTABLOQUEIA = 'B' |
| Grades de produto | Em RETORNA_QTDEESTOQUEGRADE, quando 'S', oculta grades sem saldo da pesquisa (linhas 45–47). Em MPD002/MPD020/MNF017, força Parametros[8] := 'S' para jGrade.pas (seleciona só grades com saldo) |
Checagem de ITEMLOCAL.ST_ESTOQUE | MPD002 UMPD002.pas:2185–2193 consulta ITEMLOCAL.ST_ESTOQUE antes — itens que não controlam estoque no local são ignorados |
| Base de cálculo | Depende de ST_ALERTAESTOQUENEGATIVO: 'S' → saldo comprometido; 'F' → saldo físico; 'N' → usa saldo comprometido como padrão no SQL |
| Ordem de Serviço | MOF001 UdmMOF001.pas:3055 valida saldo de peças e serviços quando 'S' |
| Orçamento | MPD018 UMPD018.pas:1217–1220 percorre tabMAQUINA para validar quando 'S' |
| Mensagem | "O Item XXX não possui saldo suficiente para operação! Quantidade necessária: ... Quantidade em Estoque: ..." (texto gerado pelas procedures VERIFICA_ESTOQUENEGATIVO*) |
Simulação passo a passo
- Acesse MFA001 → aba Ambos → subaba Opção 1
- Altere ST_ESTOQUENEGATIVO para
"Sim"e salve (F6) - Tenha um produto com saldo físico de 10 unidades (sem reservas)
- Abra um Pedido de Venda (MPD002)
- Adicione o produto com quantidade 15 → sistema dispara
JExceptioncom a mensagem "O Item XXX não possui saldo suficiente..." e cancela a inclusão do item - Adicione o produto com quantidade 8 → salvo normalmente
- Abra a pesquisa de grade de um produto com grades sem saldo → as grades zeradas não aparecem (foram filtradas por
Parametros[8] = 'S') - Tente incluir um item cuja operação (
CD_OPERACAO) não baixa estoque → não bloqueia (regra depende deflagEstoqueNegativo) - Em MOF001, crie uma OS e adicione uma peça em quantidade maior que o saldo → bloqueia a gravação
Resultado esperado: O sistema impede qualquer inclusão/gravação que deixe o estoque negativo. Também filtra grades sem saldo nas telas de pesquisa. A regra só age quando o item possui CD_OPERACAO preenchida e a operação baixa estoque.
N - Não (Permite)
| O que faz | Detalhe |
|---|---|
| Permite salvar com estoque negativo? | Sim |
| Onde age no Delphi | Os blocos if parmfatur.values['ST_ESTOQUENEGATIVO'] = 'S' (p.ex. UMPD002.pas:6664) são pulados. O item é gravado livremente |
| Onde age no SQL | VERIFICA_ESTOQUENEGATIVO* só entra no IF principal se ST_ESTOQUENEGATIVO <> 'N' OU ST_ALERTAESTOQUENEGATIVO <> 'N' (linhas 44–45 de VERIFICA_ESTOQUENEGATIVOPEDIDO.sql). Se ambos forem 'N', procedure não valida nada |
| Grade | Parâmetro [8] enviado a jGrade.RateioGrade fica vazio → grades sem saldo aparecem na pesquisa |
| Valor padrão | N — definido em UdmMFA001.pas:485 no AfterInsert da tabPARMFATUR |
Simulação passo a passo
- Acesse MFA001 → aba Ambos → Opção 1
- Altere ST_ESTOQUENEGATIVO para
"Não"(valor padrão) e salve (F6) - Tenha um produto com saldo físico de 10 unidades
- Abra um Pedido de Venda (MPD002)
- Adicione o produto com quantidade 50 → item é gravado normalmente, sem bloqueio
- Se
ST_ALERTAESTOQUENEGATIVOestiver como'S'ou'F', o usuário recebe um aviso (I-0000) mas pode prosseguir - Se ambos os parâmetros estiverem
'N', nenhum alerta/bloqueio acontece — operação é silenciosa
Resultado esperado: O usuário pode operar livremente com estoque insuficiente. O controle passa a ser apenas informativo (via ST_ALERTAESTOQUENEGATIVO) ou inexistente.
Interação com ST_ALERTAESTOQUENEGATIVO
Os dois parâmetros são complementares e agem em níveis diferentes:
ST_ESTOQUENEGATIVO | ST_ALERTAESTOQUENEGATIVO | Comportamento |
|---|---|---|
N | N | Nenhuma validação. Sistema ignora estoque negativo completamente |
N | F ou S | Só alerta. Usuário recebe aviso (I-0000) mas pode continuar. Base de cálculo: físico (F) ou comprometido (S) |
S | N | Bloqueia, sem alerta prévio. Ao salvar o item, VERIFICA_ESTOQUENEGATIVOPEDIDO retorna 'B' e o sistema lança W-0000. Em MPD002, o trecho de alerta em UMPD002.pas:6630–6631 é pulado (condição inclui ST_ESTOQUENEGATIVO = 'N') |
S | F ou S | Alerta + bloqueio. Alerta dispara antes (grid/inclusão) e o bloqueio valida novamente ao gravar. O código evita duplicar alerta quando vai bloquear (ver UMPD002.pas:6631: alerta só se ST_ESTOQUENEGATIVO = 'N') |
Pontos-chave do código
MPD002 UMPD002.pas:6630–6632 — alerta só se não vai bloquear:
if ( ((parmfatur.values['ST_ALERTAESTOQUENEGATIVO'] = 'S') or (parmfatur.values['ST_ALERTAESTOQUENEGATIVO'] = 'F'))
and (parmfatur.values['ST_ESTOQUENEGATIVO'] = 'N') and (flagEstoqueNegativo)
and ( Trim(dmMPD002.tabITEMPEDIDOCD_OPERACAO.AsString)<> '') ) then
MPD002 UMPD002.pas:6664–6665 — bloqueio:
{ Bloqueio Estoque Negativo }
if ( (parmfatur.values['ST_ESTOQUENEGATIVO'] = 'S') and
(flagEstoqueNegativo) and ( Trim(dmMPD002.tabITEMPEDIDOCD_OPERACAO.AsString)<> '') ) then
VERIFICA_ESTOQUENEGATIVOPEDIDO.sql:171–180 — decide bloqueio vs alerta:
IF ( O_DS_MENSSAGEM IS NOT NULL ) THEN
BEGIN
IF (V_ST_ESTOQUENEGATIVO = 'S') THEN
BEGIN
O_ST_ALERTABLOQUEIA = 'B';
END ELSE
BEGIN
O_ST_ALERTABLOQUEIA = 'A';
END
END
Observação Importante: Dependência de CD_OPERACAO e flagEstoqueNegativo
O bloqueio nunca dispara quando:
tabITEMPEDIDOCD_OPERACAOestá vazio (item sem operação de movimentação).flagEstoqueNegativo(flag interna) está desligada — indica que a operação não baixa estoque (MOVIMENTACAO.ST_ESTOQUENEGATIVO/TP_ESTOQUE).- Em MPD002,
TP_PEDIDO = 'O'(orçamento): o bloco de bloqueio ignora (UMPD002.pas:6668).
Itens que não controlam estoque (ITEM.ST_ESTOQUE <> 'S') ou que estão em local sem controle (ITEMLOCAL.ST_ESTOQUE) também são ignorados (verificado em UMPD002.pas:2185–2196).
Observação Importante: Filtro de Grades
Em telas com grade (MPD002 UdmMPD002.pas:1143, MPD020 UdmMPD020.pas:657, MNF017 UdmMNF017.pas:1225), quando ST_ESTOQUENEGATIVO = 'S' o Parametros[8]/ParamGrade[8] passado a jGrade.pas é forçado para 'S' ("Valida apenas Itens da Grade com Saldo"). Isso esconde grades zeradas da tela de rateio, evitando que o usuário selecione uma combinação sem saldo.
A procedure RETORNA_QTDEESTOQUEGRADE.sql:43–47 reforça esse comportamento: quando ST_ALERTAESTOQUENEGATIVO = 'N' mas ST_ESTOQUENEGATIVO = 'S', o cursor dá SUSPEND somente para grades com saldo.
Tabela Comparativa Resumida
| Opção | Descrição | Permite salvar com estoque negativo? | Filtra grades sem saldo? | Procedure retorna | Valor padrão? |
|---|---|---|---|---|---|
| S | Sim (Bloqueia) | Não (levanta JException) | Sim | O_ST_ALERTABLOQUEIA = 'B' | — |
| N | Não (Permite) | Sim | Não | O_ST_ALERTABLOQUEIA = 'A' (se alerta ativo) ou não valida | Sim |
Referências no Código Fonte
Tela MFA001 (onde o parâmetro é configurado)
source/MFA001/UMFA001.dfm:3270–3296— ComboBoxcmbST_ESTOQUENEGATIVO(Items:Sim=S,Não=N)source/MFA001/UMFA001.pas:245— Declaração do componentesource/MFA001/UdmMFA001.pas:137— CampotabPARMFATURST_ESTOQUENEGATIVO: TStringFieldsource/MFA001/UdmMFA001.pas:485— Valor padrão'N'atribuído noAfterInsertsource/MFA001/UdmMFA001.dfm:142, 1142–1147, 2378, 2537, 2751, 3022— SELECT/INSERT/UPDATE doPARMFATUR
Telas consumidoras (Delphi)
source/MPD002/UMPD002.pas:2185, 6630–6631, 6664–6665source/MPD002/UdmMPD002.pas:1143, 4268, 5745, 5938, 5972source/MPD018/UdmMPD018.pas:246, 288, 309eUMPD018.pas:1217source/MPD020/UdmMPD020.pas:240, 324, 366, 657, 955source/MNF017/UMNF017.pas:164, 198eUdmMNF017.pas:285, 1225source/MNF002/UdmMNF002.pas,source/MNF007/UdmMNF007.pas,source/MNF008/UdmMNF008.pas,source/MNF026/UdmMNF026.pas— SELECT doPARMFATURsource/MOF001/UdmMOF001.pas:446, 727, 753, 3055source/MOF002/UdmMOF002.pas— SELECT doPARMFATURsource/MPD005/UMPD005.pas,source/MPD092/UdmMPD092.pas— SELECT doPARMFATURsource/MCO006/UdmMCO006.pas— SELECT doPARMFATURsource/CPD009/UdmCPD009.dfm,source/RCA006/UdmRCA006.dfm— UPDATE/SELECT doPARMFATURsource/jGradeProduto/jGrade.pas— parâmetro[8]"Valida apenas grades com saldo"
Procedures SQL
Scripts/VERIFICA_ESTOQUENEGATIVOPEDIDO.sql:18, 29, 32, 45, 58, 150, 173, 194, 302— núcleo do bloqueio em pedidosScripts/VERIFICA_ESTOQUENEGATIVONOTA.sql— mesmo padrão em notas fiscaisScripts/VERIFICA_ESTOQUENEGATIVOOS.sql:29, 32— validação em OSScripts/RETORNA_QTDEESTOQUEGRADE.sql:25, 28, 31, 45— filtro de grades sem saldo
Backend Java
source/Server/JunsoftWebAPI/src/main/java/junsoft/erp/repository/JunsoftBuilder.javasource/Server/JunsoftWebAPI/src/main/java/junsoft/erp/repository/queries/ParmFaturSQL.javasource/Server/JunsoftWebAPI/src/main/java/junsoft/erp/service/PedidoService.java