Pular para o conteúdo principal

Seleção Automática do Lote mais Antigo (FIFO por validade)

Tela de configuração: MFA001 - Parâmetros de Faturamento Localização: Parâmetros → Faturamento → Opção 2 → campo Selecionar Lote mais Antigo [MPD002/MNF002] (habilitado somente quando TP_CONTROLELOTE = 'A' Agrupado) Tabela: PARMFATUR.ST_SELECIONALOTEANTIGO Valor padrão: não há default explícito no AfterInsert — o campo nasce vazio/NULL e é forçado a 'N' toda vez que o usuário muda TP_CONTROLELOTE para 'I' (Individual). Só pode ser editado com TP_CONTROLELOTE = 'A' (Agrupado) — ver UMFA001.pas:920, 2444, 2461-2465.

Telas impactadas​

MóduloCódigoOnde lêPapel
Tela de Rateio de Lote Agrupado (chamada por todo módulo que executa RateioLoteProducao com tipo 'SA')jLoteProducao/ULoteSaidaAgrupadoULoteSaidaAgrupado.pas:183-189 (SELECT em CarregarSaidaAgrupada), ULoteSaidaAgrupado.pas:1289 (bloco ativo if parmFatur.Values['ST_SELECIONALOTEANTIGO'] = 'S')Consumidora ativa — seleciona automaticamente os lotes mais antigos por DT_VALIDADE para cobrir a quantidade solicitada
Pedido de VendaMPD002citado no label do parâmetro — consome indiretamente via RateioLoteProducao (tipo 'SA') do jLoteProducao quando TP_CONTROLELOTE = 'A'Consumidora indireta
Nota FiscalMNF002citado no label do parâmetro — consome indiretamente via RateioLoteProducao (tipo 'SA') do jLoteProducao quando TP_CONTROLELOTE = 'A'Consumidora indireta
Parâmetros Faturamento (tela de configuração)MFA001UMFA001.dfm:3991 (label), UMFA001.dfm:4713-4741 (ComboBox cmbST_SELECIONALOTEANTIGO, items Sim=S / Não=N), UdmMFA001.dfm:1860-1865 (campo), UdmMFA001.dfm:2606, 2857 (INSERT/UPDATE de PARMFATUR)Produtora — onde o usuário configura o valor

Procedures impactadas​

Procedure / ScriptPapel
CONSOME_LOTEMATERIAPRIMA (Scripts/CONSOME_LOTEMATERIAPRIMA.sql)Consumidora — se ST_SELECIONALOTEANTIGO = 'S' e o item é semente (ST_SEMENTE <> 'N') e ainda não há lote amarrado à ordem de produção, a procedure percorre LOTESEMENTE ordenado por COALESCE(DT_VALIDADE, DT_REGISTRO) e insere os lotes mais antigos em ORDEMPRODUCAOLOTE até cobrir QT_MATERIAPRIMA. Chamada por GERA_ORDEMPRODUCAO (Scripts/GERA_ORDEMPRODUCAO.sql:199, 446).

Campos envolvidos​

CampoTabelaDescrição
ST_SELECIONALOTEANTIGOPARMFATURHabilita seleção automática FIFO de lotes por validade
TP_CONTROLELOTEPARMFATURGate de edição — só permite editar ST_SELECIONALOTEANTIGO quando = 'A' (Agrupado); se = 'I' a UI força 'N' e bloqueia o combobox (UMFA001.pas:2444, 2452)
ST_VALIDAVENCIMENTOLOTEPARMFATURLido junto no mesmo SELECT (ULoteSaidaAgrupado.pas:184) — complementa a lógica de validade do lote
ST_LOTENEGATIVOPARMESTOQUELido logo antes (ULoteSaidaAgrupado.pas:177) — controla se lote pode ficar negativo
QT_LOTEORIGEMITEM (grid do rateio)Quantidade que o auto-seleção precisa cobrir
DT_VALIDADE / DT_REGISTROLOTESEMENTECritério de ordenação — o "antigo" aqui é o de validade mais próxima (ou, na falta dela, o mais antigo pela data de registro)
NR_LOTE, QT_LOTE, CD_EMPRLOTE, CD_ITEMLOTESEMENTELotes candidatos à seleção automática
ST_SEMENTEITEMNa procedure CONSOME_LOTEMATERIAPRIMA, só consome automaticamente se <> 'N'

Tabelas gravadas​

TabelaOperaçãoOrigem
Grid interno tabLote (campos STATUS = 'Å', QT_LOTE)UPDATE em memória antes do commitULoteSaidaAgrupado.pas:1304-1349
ORDEMPRODUCAOLOTEINSERT (apenas via procedure CONSOME_LOTEMATERIAPRIMA)Scripts/CONSOME_LOTEMATERIAPRIMA.sql:53-56

Opções disponíveis​

S - Sim (Seleciona lote mais antigo automaticamente)​

O que fazDetalhe
Pré-seleção automática na tela de Rateio AgrupadoAo abrir a tela TfrmLoteAgrupado pela primeira vez (StAbrindoTela = True), o sistema soma o saldo de todos os lotes disponíveis; se a soma cobre a QT_LOTEORIGEM solicitada, percorre LOTESEMENTE ordenado por DT_VALIDADE e marca os lotes mais antigos como selecionados (STATUS = 'Å') até completar a quantidade (ULoteSaidaAgrupado.pas:1289-1349)
Consumo automático em Ordem de ProduçãoA procedure CONSOME_LOTEMATERIAPRIMA percorre LOTESEMENTE ordenado por COALESCE(DT_VALIDADE, DT_REGISTRO) e insere em ORDEMPRODUCAOLOTE os lotes mais antigos até cobrir a QT_MATERIAPRIMA (Scripts/CONSOME_LOTEMATERIAPRIMA.sql:34-63)
Requisitos na tela de configuraçãoSó fica editável quando TP_CONTROLELOTE = 'A' (Agrupado) — com 'I' (Individual) o sistema força o valor para 'N' e desabilita o combobox
Se o saldo total dos lotes é menor que a quantidade solicitadaA pré-seleção não ocorre — if (vlSaldo >= tabITEMQT_LOTEORIGEM.AsFloat) em ULoteSaidaAgrupado.pas:1289; usuário precisa escolher manualmente
Se já havia lotes marcados (iAchou > 0)A rotina é pulada — evita refazer a seleção quando o usuário já escolheu

Simulação passo a passo (Rateio Agrupado em pedido)​

  1. Vá em MFA001 → Parâmetros → Pedidos / O.S. → Opção 1
  2. Ajuste TP_CONTROLELOTE = "Agrupado" ('A') — só assim o combobox de ST_SELECIONALOTEANTIGO fica editável
  3. Marque Selecionar Lote mais Antigo = "Sim"
  4. Salve os parâmetros (F6)
  5. Cadastre um item semente (ST_SEMENTE = 'S') com dois lotes em LOTESEMENTE: lote A com DT_VALIDADE = hoje + 30 dias, lote B com DT_VALIDADE = hoje + 180 dias, ambos com saldo
  6. Em MPD002, abra pedido que dispare o rateio agrupado de lote (item semente com operação de lote)
  7. A tela de Rateio Agrupado abre — o lote A (validade mais próxima) já aparece pré-marcado com a quantidade necessária
  8. Confirme — a seleção automática evita que o usuário esqueça de usar o lote vencendo primeiro

Resultado esperado: FIFO automático por validade — lotes com vencimento mais próximo são consumidos primeiro, reduzindo perda por vencimento sem depender de escolha manual do usuário.

Simulação passo a passo (Geração de Ordem de Produção)​

  1. Mesma configuração (ST_SELECIONALOTEANTIGO = 'S')
  2. Item de matéria-prima com ST_SEMENTE <> 'N' e lotes em LOTESEMENTE
  3. Gere uma ordem de produção que chame GERA_ORDEMPRODUCAO (linhas 199 e 446 executam CONSOME_LOTEMATERIAPRIMA)
  4. Sem lotes pré-amarrados (COUNT(ORDEMPRODUCAOLOTE) = 0), a procedure percorre LOTESEMENTE por DT_VALIDADE/DT_REGISTRO ascendente e insere automaticamente em ORDEMPRODUCAOLOTE os lotes mais antigos até cobrir QT_MATERIAPRIMA

Resultado esperado: A ordem de produção nasce com os lotes de matéria-prima mais antigos já amarrados, sem intervenção manual.


N - Não (Usuário escolhe manualmente)​

O que fazDetalhe
Rateio Agrupado em telaA tela abre com a grid de lotes sem seleção automática; usuário marca manualmente os lotes desejados
Consumo automático em Ordem de ProduçãoA procedure CONSOME_LOTEMATERIAPRIMA sai no IF da linha 34 (V_ST_SELECIONALOTEANTIGO = 'S' é falso) — nenhum registro em ORDEMPRODUCAOLOTE é criado pela procedure
Quando é forçado para 'N'Sempre que TP_CONTROLELOTE muda para 'I' (Individual), o evento cmbTP_CONTROLELOTEChange em UMFA001.pas:2444 grava ST_SELECIONALOTEANTIGO = 'N' e desabilita o combobox

Simulação passo a passo​

  1. MFA001 → Selecionar Lote mais Antigo = "Não" (ou simplesmente deixe TP_CONTROLELOTE = 'I' — o sistema força)
  2. Salve (F6)
  3. No fluxo de pedido/nota com rateio agrupado, a grid de lotes abre sem pré-seleção — usuário escolhe os lotes manualmente
  4. Na geração de Ordem de Produção, nenhum lote de matéria-prima é amarrado automaticamente via CONSOME_LOTEMATERIAPRIMA — o controle fica a cargo do usuário

Resultado esperado: Controle 100% manual de lotes; útil quando as regras de consumo não são puramente FIFO por validade.


Interação com TP_CONTROLELOTE e parâmetros de lote relacionados​

ParâmetroRelação
TP_CONTROLELOTEGate de edição. ST_SELECIONALOTEANTIGO só é editável quando TP_CONTROLELOTE = 'A' (Agrupado). Ao trocar para 'I' (Individual), o sistema grava 'N' e desabilita o combobox (UMFA001.pas:2442-2452). Na reabertura da tela, a mesma regra é aplicada em UMFA001.pas:920.
ST_VALIDAVENCIMENTOLOTELido no mesmo SELECT de CarregarSaidaAgrupada (ULoteSaidaAgrupado.pas:184-188) — ambos tratam do ciclo de vida do lote na saída agrupada.
ST_LOTEPEDIDOÉ quem dispara o rateio de lote no pedido. Sem ST_LOTEPEDIDO = 'S' a tela de rateio nem chega a abrir, e portanto ST_SELECIONALOTEANTIGO nunca é usado no fluxo de pedido.
ST_LOTENEGATIVO (PARMESTOQUE)Também lido em CarregarSaidaAgrupada (ULoteSaidaAgrupado.pas:177-181) — permite (ou não) que a seleção automática consuma lotes com saldo zerado.

Tabela Comparativa Resumida​

OpçãoDescriçãoPré-seleção FIFO na tela de Rateio Agrupado?CONSOME_LOTEMATERIAPRIMA consome auto?Exige TP_CONTROLELOTE = 'A' para editar?
SSim — seleciona lote mais antigoSim (se saldo total cobre a quantidade)Sim (quando ST_SEMENTE <> 'N' e não há lote amarrado)Sim
NNão — seleção manualNãoNão— (valor forçado quando TP_CONTROLELOTE = 'I')

Referências no Código Fonte​

ArquivoLinha(s)Papel
source/MFA001/UMFA001.dfm3991-4004 (label "Selecionar Lote mais Antigo [MPD002/MNF002]"), 4713-4741 (ComboBox cmbST_SELECIONALOTEANTIGO, items Sim=S / Não=N)UI do parâmetro
source/MFA001/UMFA001.pas538-539 (declaração), 920 (habilita combobox só quando TP_CONTROLELOTE = 'A'), 2444 (força 'N' quando muda para Individual), 2448/2452 (ReadOnly+Enabled=False no modo Individual), 2461/2465 (libera no modo Agrupado)Regra de edição
source/MFA001/UdmMFA001.dfm1860-1865 (TStringField), 2606 (parâmetro no INSERT), 2857 (parâmetro no UPDATE)Persistência
source/MFA001/UdmMFA001.pas263 (declaração do campo). Não há atribuição no AfterInsert (campo nasce vazio)Persistência
source/jLoteProducao/ULoteSaidaAgrupado.pas104 (var iST_SELECIONALOTEANTIGO), 183-189 (SELECT em CarregarSaidaAgrupada), 1289-1349 (bloco ativo: pré-seleção FIFO dos lotes mais antigos na grid tabLote com STATUS = 'Å')Consumidora principal (UI)
source/jLoteProducao/jLote.pas54-55 (roteamento tipo = 'SA' → CarregarSaidaAgrupada)Entry point do rateio agrupado (RateioLoteProducao)
Scripts/CONSOME_LOTEMATERIAPRIMA.sql15-20 (SELECT do parâmetro), 34-63 (bloco ativo V_ST_SELECIONALOTEANTIGO = 'S' — loop FIFO por COALESCE(DT_VALIDADE, DT_REGISTRO) inserindo em ORDEMPRODUCAOLOTE)Consumidora principal (SQL)
Scripts/GERA_ORDEMPRODUCAO.sql199, 446 (chamadas a CONSOME_LOTEMATERIAPRIMA)Invoca o consumo FIFO na geração da ordem

Observação 1: O label do parâmetro cita [MPD002/MNF002], mas essas telas não referenciam ST_SELECIONALOTEANTIGO diretamente — o consumo é transitivo via jLoteProducao.RateioLoteProducao (tipo 'SA' = Saída Agrupada).

Observação 2: "Lote mais antigo" no contexto deste parâmetro significa validade mais próxima (DT_VALIDADE ascendente), não data de criação. Na procedure SQL, como fallback usa DT_REGISTRO quando DT_VALIDADE é NULL (COALESCE(DT_VALIDADE, DT_REGISTRO)).

Observação 3: O parâmetro depende do gate TP_CONTROLELOTE = 'A' — em modo Individual o sistema obriga 'N'. Consequência prática: ambientes com rateio Individual nunca têm seleção FIFO automática.