Pular para o conteúdo principal

NR_DIASRETIRADA - Dias para próxima retirada após devolução de item locado

Tela: MFA001 - Parâmetros de Faturamento Localização: Parâmetros → Faturamento → aba Locações (pagLocacao em UMFA001.dfm:10630) → GroupBox5 ' Parâmetros de Locações ' → campo Dias para Próx. Retirada após Devolução (label Label68 em UMFA001.dfm:10660-10674, Caption = 'Dias para Próx. Retirada após Devolução', FocusControl = DBEdit1, posicionado em Left=18, Top=46) Tabela: PARMFATUR.NR_DIASRETIRADA Tipo: Numérico inteiro (dias) — DOM_INTEGER no DDL (docs/schema/tables/PARMFATUR.sql:152); TIntegerField no client (UdmMFA001.pas:202, UdmMFA001.dfm:1506-1510) com Alignment = taCenter; editado via TDBEdit DBEdit1 (UMFA001.dfm:10812-10828). Valor padrão: NULL — o AfterInsert de tabPARMFATUR em UdmMFA001.pas:434 não atribui default para este campo. O DDL (DOM_INTEGER) também não define DEFAULT, então o campo nasce vazio. As procedures que o consomem aplicam COALESCE(P.NR_DIASRETIRADA, 0) para tratar o NULL como zero. Validação (MFA001): não há OnValidate para tabPARMFATURNR_DIASRETIRADA em UdmMFA001.pas. Qualquer inteiro é aceito, inclusive 0 e negativos.

O que o parâmetro faz​

NR_DIASRETIRADA é o número de dias de "quarentena" aplicado entre a devolução de um item locado e sua próxima retirada — um período pós-devolução durante o qual o item não deve voltar a ser locado. É usado pelas procedures de saldo de locação (RETORNA_SALDO_LOCACAO e RETORNA_SALDO_LOCACAOTROCA) para:

  1. Calcular O_DT_PROXRETIRADA — a data a partir da qual o item voltaria a estar disponível após uma devolução. É sempre DT_DEVOLUCAOMIN + NR_DIASRETIRADA.
  2. Ajustar a janela de contagem de itens retornados — para determinar a disponibilidade de um item em uma nova locação, a procedure precisa considerar retornos ocorridos nos NR_DIASRETIRADA - 1 dias anteriores à data solicitada (itens devolvidos há pouco ainda estão em quarentena e não podem ser contados como "livres").

O objetivo operacional é permitir que a empresa configure um intervalo técnico de manutenção/inspeção entre locações do mesmo item (ex.: pneus de locação que precisam de 2 dias para revisão antes de sair para outro cliente).

Telas impactadas​

MóduloCódigoPapel
Parâmetros de FaturamentoMFA001Produtora — cadastra/edita o valor no campo DBEdit1 (aba Locações). CRUD da PARMFATUR inclui o campo em SELECT/INSERT/UPDATE (UdmMFA001.dfm:211, 2405, 2571, 2801, 3091).
LocaçõesMPD043Consumidora direta — em ValidaDisponibilidadeItem (UdmMPD043.pas:3003) lê PARMFATUR.NR_DIASRETIRADA diretamente e passa implicitamente para as procedures ao chamar RETORNA_SALDO_LOCACAO.

Procedures impactadas​

ProcedurePapel
RETORNA_SALDO_LOCACAOConsumidora principal. Lê COALESCE(P.NR_DIASRETIRADA, 0) na linha 147-150. Usa o valor para (a) calcular O_DT_PROXRETIRADA = DATEADD(V_NR_DIASRETIRADA DAY TO V_DT_DEVOLUCAOMIN) (linhas 439 e 445) e (b) definir V_DT_ANTERIORRET = DATEADD(- V_NR_DIASRETIRADA + 1 DAY TO I_DT_INICIAL) (linha 518), usado no laço de contagem de itens em quarentena.
RETORNA_SALDO_LOCACAOTROCAConsumidora secundária (variante para troca). Mesma lógica: lê COALESCE(P.NR_DIASRETIRADA, 0) nas linhas 96-99, calcula O_DT_PROXRETIRADA (linhas 340 e 346) e V_DT_ANTERIORRET (linha 401).

Campos envolvidos​

CampoTabelaPapel
NR_DIASRETIRADAPARMFATURDias de quarentena pós-devolução (este parâmetro).
DT_RETIRADALOCACAOData solicitada para retirada na nova locação — é o I_DT_INICIAL passado às procedures.
DT_DEVOLUCAOLOCACAOData prevista de devolução da locação em análise — é o I_DT_FINAL.
DT_DEVOLUCAOLOCACAODEVOLData de devolução efetiva do item (locações anteriores). A procedure busca a menor data de devolução no período (V_DT_DEVOLUCAOMIN) e é sobre ela que NR_DIASRETIRADA é somado.
ST_LOCACAOLOCACAOFiltro: IN ('P','T') — locações pendentes / em trânsito.
ST_LOCADO / ST_TROCADOLOCACAOITEMFiltros: ST_LOCADO = 'S', ST_TROCADO = 'N'.
O_DT_PROXRETIRADAsaídaData calculada a partir da qual o item pode ser retirado novamente.
O_ST_DISPRETIRADAsaída'S' / 'N' / 'F' — flag de disponibilidade para a data solicitada.

Comportamento / Regra​

Valor = 0 (ou NULL)​

AspectoComportamento
Consulta nas proceduresSELECT COALESCE(P.NR_DIASRETIRADA, 0) INTO V_NR_DIASRETIRADA — NULL é tratado como 0.
O_DT_PROXRETIRADADATEADD(0 DAY TO V_DT_DEVOLUCAOMIN) = própria data de devolução. Item fica disponível já no dia em que é devolvido.
Janela de quarentena (V_DT_ANTERIORRET)DATEADD(0 + 1 DAY TO I_DT_INICIAL) = I_DT_INICIAL + 1. O laço WHILE (V_DT_AUX <= I_DT_INICIAL) não executa nenhuma iteração (condição I_DT_INICIAL + 1 <= I_DT_INICIAL é falsa) → nenhum dia anterior é considerado em quarentena.
NR_DIASRETIRADA IS NULL literalmenteNo bloco IF((V_NR_DIASRETIRADA IS NOT NULL) AND (O_QT_LIVRE > 0)) (linha 443), como a SELECT usa COALESCE, V_NR_DIASRETIRADA nunca é NULL na prática — o ramo sempre entra se houver saldo livre.

Resultado esperado: o parâmetro fica inativo. Itens podem ser realocados no mesmo dia da devolução, sem quarentena.

Valor > 0​

AspectoComportamento
LeituraCOALESCE(P.NR_DIASRETIRADA, 0) retorna o inteiro configurado.
O_DT_PROXRETIRADA (saldo livre)DATEADD(V_NR_DIASRETIRADA DAY TO V_DT_DEVOLUCAOMIN) — acrescenta os dias de quarentena à menor data de devolução encontrada no período.
O_DT_PROXRETIRADA (sem saldo livre)DATEADD(COALESCE(V_NR_DIASRETIRADA, 0) DAY TO V_DT_DEVOLUCAOMIN) — mesmo cálculo, indicando a data em que o item poderia estar disponível novamente.
Janela retroativa de contagemV_DT_ANTERIORRET = DATEADD(- V_NR_DIASRETIRADA + 1 DAY TO I_DT_INICIAL). O laço percorre de V_DT_ANTERIORRET até I_DT_INICIAL, somando LI.QT_ITEM das devoluções ocorridas nesses dias. O total V_QT_RET é subtraído do saldo de estoque — itens ainda em "quarentena de retirada" não contam como livres para a data solicitada.
Decisão finalSe V_QT_RET <= 0 após a subtração, O_ST_DISPRETIRADA = 'N' (indisponível).

Simulação passo a passo​

Pré-requisitos do cenário:

  • PARMFATUR.NR_DIASRETIRADA = 2 definido em MFA001 → aba Locações.
  • Item CD_ITEM = 500 com saldo de estoque = 3 unidades na empresa 1.
  • Locações anteriores para o item 500:
    • Locação 800 → DT_RETIRADA = 10/05/2026, DT_DEVOLUCAO = 13/05/2026, QT_ITEM = 2, devolvido em LOCACAODEVOL.DT_DEVOLUCAO = 13/05/2026.
  • Operador está tentando criar nova locação do item 500 para DT_RETIRADA = 14/05/2026, DT_DEVOLUCAO = 16/05/2026, QT_ITEM = 3.
  1. Em MFA001 → aba Locações → informe Dias para Próx. Retirada após Devolução = 2. Salve (F6). Valor grava em PARMFATUR.NR_DIASRETIRADA.
  2. Em MPD043, ao incluir o item 500 na nova locação, o sistema executa ValidaDisponibilidadeItem (UdmMPD043.pas:3003), que chama RETORNA_SALDO_LOCACAO(500, 1, '14/05/2026', '16/05/2026', 'L', :nova_locacao).
  3. Dentro da procedure:
    1. SELECT COALESCE(NR_DIASRETIRADA, 0) INTO V_NR_DIASRETIRADA → V_NR_DIASRETIRADA = 2 (linha 147-150).
    2. Calcula V_DT_DEVOLUCAOMIN buscando a menor LD.DT_DEVOLUCAO das locações ativas que ainda não devolveram → suponha que encontre 13/05/2026.
    3. Como há saldo livre (O_QT_LIVRE > 0), entra no bloco IF((V_NR_DIASRETIRADA IS NOT NULL) AND (O_QT_LIVRE > 0)) (linha 443).
    4. O_DT_PROXRETIRADA = DATEADD(2 DAY TO 13/05/2026) = 15/05/2026 (linha 445).
    5. Calcula janela retroativa: V_DT_ANTERIORRET = DATEADD(-2 + 1 DAY TO 14/05/2026) = 13/05/2026 (linha 518).
    6. Laço WHILE (V_DT_AUX <= 14/05/2026) percorrendo 13/05 e 14/05:
      • 13/05 → encontra a devolução da Locação 800 (LD.DT_DEVOLUCAO = 13/05/2026 com QT_ITEM = 2) → V_QT_RET = 2.
      • 14/05 → não há devoluções → V_QT_RET segue 2.
    7. V_QT_RET = V_QT_SALDOESTOQUE - V_QT_RET = 3 - 2 = 1 (linha 544).
    8. V_QT_RET (1) <= 0? Não, então segue sem marcar como indisponível por esse critério. Mas O_QT_LIVRE (calculado antes) já refletia saldo real descontando as 2 unidades em quarentena.
  4. O resultado retornado à MPD043 indica que apenas 1 unidade está efetivamente livre para 14/05/2026 (as 2 unidades devolvidas em 13/05 ainda estão em quarentena). Como o operador pediu 3, o item é marcado como Indisponível e a mensagem "Produto ... indisponível para a data 14/05/2026. Quantidade Solicitada: 3. Quantidade Disponível: 1." é levantada como W-0000 em UdmMPD043.pas:3055.

Resultado esperado: itens devolvidos menos de NR_DIASRETIRADA dias antes da data de retirada solicitada não contam como disponíveis; a procedure exibe a DT_PROXRETIRADA ajustada (data de devolução + quarentena) para orientar o operador sobre quando o item voltará a estar livre.

Casos de borda​

CenárioComportamento
NR_DIASRETIRADA = 1V_DT_ANTERIORRET = DATEADD(0 DAY TO I_DT_INICIAL) = I_DT_INICIAL. O laço executa uma única vez (para a própria data solicitada) → conta apenas devoluções ocorridas no mesmíssimo dia da retirada.
NR_DIASRETIRADA negativoO DDL não impede (DOM_INTEGER), e não há validação em MFA001. Resultado matemático: DATEADD(- N DAY TO I_DT_INICIAL) geraria uma data futura em relação a I_DT_INICIAL, fazendo o WHILE não executar (condição inicial já falsa). Configuração incorreta — evitar.
Sem locações devolvidas no períodoV_DT_DEVOLUCAOMIN resulta da combinação de LOCACAODEVOL e LOCACAO; se não houver devoluções, O_DT_PROXRETIRADA é calculado sobre a data mínima disponível no contexto (ver blocos específicos da procedure).
O_QT_LIVRE = 0Entra no ramo da linha 437-441: O_DT_PROXRETIRADA = DATEADD(COALESCE(V_NR_DIASRETIRADA, 0) DAY TO V_DT_DEVOLUCAOMIN) e O_ST_DISPRETIRADA = 'N'.
Locação tipo 'V' (venda)Em RETORNA_SALDO_LOCACAO, o bloco específico de locação-venda (a partir da linha 552) contém lógica extra, mas não reutiliza V_NR_DIASRETIRADA nessa verificação adicional — só na parte comum de cálculo de O_DT_PROXRETIRADA.

Referências no Código Fonte​

Delphi — MFA001 (cadastro do parâmetro)​

ArquivoLinhasPapel
source/MFA001/UMFA001.dfm10630-10631TTabSheet pagLocacao com Caption = 'Locações'
source/MFA001/UMFA001.dfm10638TGroupBox GroupBox5 ' Parâmetros de Locações ' (container visual)
source/MFA001/UMFA001.dfm10660-10674TLabel Label68 com Caption = 'Dias para Próx. Retirada após Devolução', FocusControl = DBEdit1, Left=18, Top=46
source/MFA001/UMFA001.dfm10812-10828TDBEdit DBEdit1 — DataField = 'NR_DIASRETIRADA', DataSource = dmMFA001.dsPARMFATUR, Left=221, Top=41, Width=66, Height=21
source/MFA001/UdmMFA001.pas202Declaração tabPARMFATURNR_DIASRETIRADA: TIntegerField
source/MFA001/UdmMFA001.pas434tabPARMFATURAfterInsert não atribui default para NR_DIASRETIRADA (o campo nasce NULL)
source/MFA001/UdmMFA001.dfm211, 3091SelectSQL / RefreshSQL: PARMFATUR.NR_DIASRETIRADA, PARMFATUR.HR_INTERVALORET, ...
source/MFA001/UdmMFA001.dfm1506-1510Definição do TIntegerField com FieldName = 'NR_DIASRETIRADA', Alignment = taCenter, Origin = '"PARMFATUR"."NR_DIASRETIRADA"'
source/MFA001/UdmMFA001.dfm2405InsertSQL: inclui NR_DIASRETIRADA na cláusula de colunas
source/MFA001/UdmMFA001.dfm2571InsertSQL: VALUES (..., :NR_DIASRETIRADA, ...)
source/MFA001/UdmMFA001.dfm2801UpdateSQL: NR_DIASRETIRADA = :NR_DIASRETIRADA,

Delphi — MPD043 (consumidora)​

ArquivoLinhasPapel
source/MPD043/UdmMPD043.pas3003-3143Procedure livre ValidaDisponibilidadeItem — contém a chamada à procedure RETORNA_SALDO_LOCACAO
source/MPD043/UdmMPD043.pas3008Declaração Nr_DiasRetirada: Integer
source/MPD043/UdmMPD043.pas3019-3024Leitura local do parâmetro: SELECT P.NR_DIASRETIRADA FROM PARMFATUR P WHERE P.CD_EMPRESA = ... → Nr_DiasRetirada := StrToInt(Resultado[0]) (variável é declarada, mas o cálculo efetivo ocorre dentro das procedures chamadas em seguida)
source/MPD043/UdmMPD043.pas3025-3035Chamada da procedure RETORNA_SALDO_LOCACAO — o parâmetro é relido internamente pela procedure

DDL​

  • docs/schema/tables/PARMFATUR.sql:152 — NR_DIASRETIRADA DOM_INTEGER, (sem NOT NULL, sem default → permite NULL; consumidores aplicam COALESCE(..., 0)).

SQL — Procedures​

ArquivoLinhasPapel
Scripts/RETORNA_SALDO_LOCACAO.sql28declare variable V_NR_DIASRETIRADA integer;
Scripts/RETORNA_SALDO_LOCACAO.sql147-150Leitura: SELECT COALESCE(P.NR_DIASRETIRADA, 0) FROM PARMFATUR P WHERE P.CD_EMPRESA = :I_CD_EMPRESA INTO V_NR_DIASRETIRADA — comentário documenta: "Parâmetro Dias para Próx Retirada após Devolução [MFA001]"
Scripts/RETORNA_SALDO_LOCACAO.sql439Ramo O_QT_LIVRE = 0: O_DT_PROXRETIRADA = DATEADD(COALESCE(V_NR_DIASRETIRADA, 0) DAY TO V_DT_DEVOLUCAOMIN)
Scripts/RETORNA_SALDO_LOCACAO.sql443-445Ramo com saldo livre: IF((V_NR_DIASRETIRADA IS NOT NULL) AND (O_QT_LIVRE > 0)) THEN ... O_DT_PROXRETIRADA = DATEADD(V_NR_DIASRETIRADA DAY TO V_DT_DEVOLUCAOMIN)
Scripts/RETORNA_SALDO_LOCACAO.sql518Janela retroativa: V_DT_ANTERIORRET = DATEADD(- V_NR_DIASRETIRADA + 1 DAY TO I_DT_INICIAL) — base do laço WHILE que soma devoluções em quarentena (linhas 521-541)
Scripts/RETORNA_SALDO_LOCACAOTROCA.sql28declare variable V_NR_DIASRETIRADA integer;
Scripts/RETORNA_SALDO_LOCACAOTROCA.sql96-99Leitura: SELECT COALESCE(P.NR_DIASRETIRADA, 0) FROM PARMFATUR P WHERE P.CD_EMPRESA = :I_CD_EMPRESA INTO V_NR_DIASRETIRADA
Scripts/RETORNA_SALDO_LOCACAOTROCA.sql340Ramo O_QT_LIVRE = 0: O_DT_PROXRETIRADA = DATEADD(COALESCE(V_NR_DIASRETIRADA, 0) DAY TO V_DT_DEVOLUCAOMIN)
Scripts/RETORNA_SALDO_LOCACAOTROCA.sql344-346Ramo com saldo livre: análogo à RETORNA_SALDO_LOCACAO
Scripts/RETORNA_SALDO_LOCACAOTROCA.sql401V_DT_ANTERIORRET = DATEADD(- V_NR_DIASRETIRADA + 1 DAY TO I_DT_INICIAL)