Árvore de páginas

DESCONTO POR LOTE / VIDA ÚTIL DO PRODUTO (SHELF-LIFE)

Produto: Automação da Força de Vendas
Linha de Produto: TOTVS CRM
Segmento: Cross Segmentos
Módulo: Venda
Aplicação: Web/app móvel
Identificador: DTSFAPD-2128
     

    VISÃO GERAL

O recurso possibilita a implementação de descontos estratégicos em produtos, levando em consideração o período que resta até o vencimento de seus respectivos lotes. Essa funcionalidade é particularmente vantajosa em situações envolvendo produtos com prazos de validade, onde se busca estimular a comercialização dos lotes prestes a expirar.


    OBJETIVO

Melhorar a eficiência das vendas ao gerenciar lotes de produtos com base em suas datas de validade, evitando perdas por vencimento, otimizando a gestão de estoque.


  ANTES DE COMEÇAR

Requisitos

Para utilizar o recurso, certifique-se de estar usando a versão padrão da solução.

  DETALHES FUNCIONAIS

Funções

  1. Configuração de Lotes e Vida Útil: Relaciona lotes aos produtos e define a vida útil. Base para cálculo de descontos por vencimento.

  2. Configuração de Faixas de Vida Útil: Cadastra faixas de dias/percentuais.

  3. Configuração de Descontos por Faixa de Vida Útil: Associa descontos a faixas de vencimento. Estimule vendas próximas ao vencimento.

  4. Campos de Lote no Pedido: Exibe/edita dados de lote, dias e % de vida útil. Facilita escolha e visualização.

  COMO USAR?

Passo a Passo

  1. Crie um novo pedido de venda ou abra um existente.

  2. Na seção de produtos do pedido, encontre o item para o qual você deseja aplicar o desconto com base na vida útil do lote.

  3. Na coluna "Lote" associada ao item, clique na opção de seleção.

  4. Uma lista suspensa de lotes disponíveis para o produto será exibida. Selecione o lote específico que você deseja vincular ao item.

  5. Assim que o lote for selecionado, as informações sobre o lote serão exibidas imediatamente ao lado do item, como "Dias Fim Vida Útil" e "% Desconto".

  6. Verifique os "Dias Fim Vida Útil" para entender quantos dias restam até o vencimento do lote.

  7. Observe o "% Desconto" que foi calculado automaticamente com base nas configurações de vida útil do lote.

  8. Se tudo estiver conforme o esperado, prossiga normalmente com a criação do pedido.


 EXEMPLO PRÁTICO

Caso de uso

Cenário:

A "Loja de Suplementos FitLife" é uma distruidora especializada em produtos para nutrição esportiva.Visam maximizar as vendas de produtos com datas de validade próximas.


Desafio Antigo:

Produtos com datas de validade próximas frequentemente não eram vendidos a tempo, resultando em prejuízos para a "Loja de Suplementos FitLife".


Solução Atualizada:

"Distribuidora" conseguiu acelerar as vendas de produtos próximos ao vencimento, evitando perdas de estoque e maximizando as receitas.


  DETALHES TÉCNICOS


IMPORTAÇÃO DE LOTES DA TABELA SB8

DE PARA
DEPARAB8_FILIAL lote.idestoque_B8_QTDORI
DEPARAB8_FILIAL lote.quantidadeoriginal
B8_PRODUTO lote.idestoque_B8_LOCAL
lote.idestoque_B8_DATA B8_DTVALID
lote.datainicio lote.datafim
B8_SALDO lote.quantidade
lote.B8_DOC + '-' + lote.B8_SERIE lote.codigo
lote.B8_DOC + '-' + lote.B8_SERIE + ': ' + lote.B8_DTVALID lote.descricao

1. CADASTRO

Através da ferramenta "tools", selecione a opção 3 para adicionar a coluna "quantidadeoriginal" na tabela "lote":

quantidadeoriginal: decimal(18,6), nullable

Usando novamente a opção 3, crie a tabela "faixavidautil" com os seguintes campos:


        idfaixavidautil: PK
        codigo: varchar(20), not-null
        descricao: varchar(80), not-null
        idnativo: byte, not-null, default 1
        cor: varchar(6), nullable
        percentualinicial: decimal(18,6), nullable
        percentualfinal: decimal(18,6), nullable
        numerodiasinicial: decimal(18,6), nullable
        numerodiasfinal: decimal(18,6), nullable
    

Também pela opção 3, adicione a coluna "idfaixavidautil" na tabela "desconto" como FK para "faixavidautil" e "idlote" como FK para "lote":

idfaixavidautil: FK para tabela faixavidautil, nullable idlote: FK para a tabela lote, nullable

2. IMPLEMENTAÇÃO NA TELA

Na seção de vínculos de desconto, inclua campos de pesquisa para as entidades:

  • Faixa vida útil: identificado como "Faixa vida útil"
  • Lote: identificado como "Lote"

Os campos "descrição" das entidades serão exibidos na tela de pesquisa.

3. CADASTRO DE "FAIXA VIDA ÚTIL"

Sob o menu "Cadastro > Venda", adicione uma nova tela para cadastro de "Faixa vida útil" com os seguintes campos no grid:

  • "Código": Campo de texto para inserção do código, persistindo em "faixavidautil.codigo"
  • "Descrição": Campo de texto para a descrição, persistindo em "faixavidautil.descricao"
  • "Situação": Checkbox com opções "Sim/Não" para definir a situação, persistindo em "faixavidautil.idnativo"
  • "Cor": Seleção de cor baseada nas configurações do tema, persistindo o código hexadecimal em "faixavidautil.cor"
  • "Percentual inicial": Campo numérico, arredondamento considerando parâmetros de porcentagem, persistindo em "faixavidautil.percentualinicial"
  • "Percentual final": Campo numérico, arredondamento considerando parâmetros de porcentagem, persistindo em "faixavidautil.percentualfinal"
  • "Núm. dias inicial": Campo numérico, arredondamento considerando parâmetros gerais, persistindo em "faixavidautil.numerodiasinicial"
  • "Núm. dias final": Campo numérico, arredondamento considerando parâmetros gerais, persistindo em "faixavidautil.numerodiasfinal"

A gravação será bloqueada caso haja valores nos campos de percentual e número de dias simultaneamente.


Novos Parâmetros do Sistema

Configuração de Campos dos Itens (Configuração > Configuração Pedido > Produto)

  • ANDROID_CARD_LOTE
  • ANDROID_CARRINHO_LOTE
  • ANDROID_NEGOCIACAO_LOTE
  • WEB_GRID_LOTE
  • ANDROID_CARD_DIAS_VIDAUTIL - Não haverá implementação para as colunas Editável e Obrigatório, podendo ser fixas "-"
  • ANDROID_CARRINHO_DIAS_VIDAUTIL - Não haverá implementação para as colunas Editável e Obrigatório, podendo ser fixas "-"
  • ANDROID_NEGOCIACAO_DIAS_VIDAUTIL - Não haverá implementação para as colunas Editável e Obrigatório, podendo ser fixas "-"
  • WEB_GRID_DIAS_VIDAUTIL - Não haverá implementação para as colunas Editável e Obrigatório, podendo ser fixas "-"
  • ANDROID_CARD_PERCENTUAL_VIDAUTIL - Não haverá implementação para as colunas Editável e Obrigatório, podendo ser fixas "-"
  • ANDROID_CARRINHO_PERCENTUAL_VIDAUTIL - Não haverá implementação para as colunas Editável e Obrigatório, podendo ser fixas "-"
  • ANDROID_NEGOCIACAO_PERCENTUAL_VIDAUTIL - Não haverá implementação para as colunas Editável e Obrigatório, podendo ser fixas "-"
  • WEB_GRID_PERCENTUAL_VIDAUTIL

Tela de Busca de Descontos (Configuração > Configuração Pedido > Busca Produto > DESCONTO)

O sistema deverá receber 2 novos campos na determinação dos filtros gerais e níveis, sendo eles:

  • PRODUTO_IDLOTE
  • PRODUTO_IDFAIXAVIDAUTIL

Tela de Busca de Produtos (Configuração > Configuração Pedido > Busca Produto)

O sistema deverá implementar busca de LOTE baseado no registro novo da wsconfigpedidocampo, de código "PEDIDOPRODUTO_LOTE"

Tabelas Selecionáveis

Lote

Registros de Cláusulas WHERE Selecionáveis:

  • PRODUTO_IDESTOQUE: lote.idestoque = id do estoque do cache para o produto em questão
  • QUANTIDADE: operação editável com opções de campo numérico (GT, LT, LE, GE...) para comparar com lote.quantidade
  • QUANTIDADEORIGINAL: operação editável com opções de campo numérico (GT, LT, LE, GE...)
  • VIGENCIA: current_date between LOTE.datainicio and LOTE.datafim
  • DIASFIM_VIDAUTIL: operação editável com opções de campo numérico (GT, LT, LE, GE...)
  • PERCENTUAL_VIDAUTIL: operação editável com opções de campo numérico (GT, LT, LE, GE...)

Parâmetros Gerais do Pedido (Configuração > Configuração Pedido > Geral)

Deverá existir novo parâmetro:

  • "VIDAUTIL_CONSIDERA_DIAS_UTEIS": inativo por padrão
  • Descrição: "Quando ativo, desconsidera finais de semana e registros de datas comemorativas (datacomemorativa.idnferiado = 1)"

Implementação no Pedido de Venda

Tela de Pedidos de Venda - Contexto de Itens

O sistema deverá implementar os seguintes novos campos:

  • Campo "Lote", campo de pesquisa, seleção única, cuja tela de pesquisa (dialog) exiba os campos lote.descricao e lote.quantidade (desconsiderar movimentações definidas no tópico 3). O campo deverá respeitar as configurações dos parâmetros:
    ANDROID_CARD_LOTE
    ANDROID_CARRINHO_LOTE
    ANDROID_NEGOCIACAO_LOTE
    WEB_GRID_LOTE
    A consulta das opções selecionáveis será: Resultado da configuração de filtros gerais e níveis da busca produto > LOTE
  • Campo "Dias fim vida útil", decimal (arredondamento: QTD_CASAS_DECIMAIS e MODO_ARREDONDAMENTO_GERAL). O campo deverá respeitar as configurações dos parâmetros:
    ANDROID_CARD_DIAS_VIDAUTIL
    ANDROID_CARRINHO_DIAS_VIDAUTIL
    ANDROID_NEGOCIACAO_DIAS_VIDAUTIL
    WEB_GRID_DIAS_VIDAUTIL
    O campo será somente leitura, cujo valor exibido será o resultado da fórmula a seguir:
    lote.datafim (lote selecionado no item) - DATA ATUAL
    Validar o parâmetro VIDAUTIL_CONSIDERA_DIAS_UTEIS para considerar ou não os finais de semana e datas comemorativas (datacomemorativa.idnferiado = 1)
  • Campo "% vida útil", decimal (arredondamento: QTD_CASAS_DECIMAIS_PORCENTAGEM e MODO_ARREDONDAMENTO_PORCENTAGEM). O campo deverá respeitar as configurações dos parâmetros:
    ANDROID_CARD_PERCENTUAL_VIDAUTIL
    ANDROID_CARRINHO_PERCENTUAL_VIDAUTIL
    ANDROID_NEGOCIACAO_PERCENTUAL_VIDAUTIL
    WEB_GRID_PERCENTUAL_VIDAUTIL
    O campo será somente leitura, cujo valor exibido será o resultado da fórmula a seguir:
    (DATA ATUAL - lote.datainicio (lote selecionado no item)) / (lote.datafim (lote selecionado no item) - lote.datainicio (lote selecionado no item)) * 100
    Validar o parâmetro VIDAUTIL_CONSIDERA_DIAS_UTEIS para considerar ou não os finais de semana e datas comemorativas (datacomemorativa.idnferiado = 1)

Filtro de Descontos

PRODUTO_IDLOTE

A cláusula WHERE dessa configuração será:

WHERE desconto.idlote = ${lote selecionado na linha do item}

PRODUTO_IDFAIXAVIDAUTIL

A cláusula WHERE dessa configuração será:


      WHERE desconto.idfaixavidautil IN (
    SELECT idfaixavidautil FROM faixavidautil
    WHERE (
        -- Comparando registros cadastrados com faixa de percentual
        percentualinical IS NOT NULL
        AND percentualfinal IS NOT NULL
        AND ${Campo "% vida útil"} >= percentualinical
        AND ${Campo "% vida útil"} <= percentualfinal
    ) OR (
        -- Comparando registros cadastrados com faixa de numero de dias
        numerodiasinicial IS NOT NULL
        AND numerodiasfinal IS NOT NULL
        AND ${Campo "Dias fim vida útil"} >= numerodiasinicial
        AND ${Campo "Dias fim vida útil"} <= numerodiasfinal
    )
    )  

Parâmetro "CHAVE_UNICA_PRODUTOS_DUPLICADOS"

O parâmetro "CHAVE_UNICA_PRODUTOS_DUPLICADOS" deve implementar o valor configurado "idlote", para que a nova coluna de "Lote" possa servir como chave combinada para não permitir que múltiplos itens da pedidoproduto compartilhem as mesmas chaves combinadas, quando o parâmetro "HABILITAR_INCLUSAO_PRODUTO_DUPLICADO" estiver ativo.

A descrição do parâmetro "CHAVE_UNICA_PRODUTOS_DUPLICADOS" deverá ser alterada para:

Definição de quais FK da PedidoProduto, separadas por virgula, não podem estar repetidas no pedido. Valores aceitáveis: idproduto, idtipopedido, idlote

Validação de Quantidade de Lote + Movimentação de Quantidades de Lote

Pelo tools, opção 3, o sistema deve criar a tabela lotemovimento:

  • idlotemovimento: PK
  • idlote: FK para lote, not-null
  • quantidade: decimal(18,6), not-null
  • idnativo: byte, not-null, default 1
  • idnprocessado: byte, not-null, default 0
  • idpedidoproduto: fk para pedidoproduto, nullable

No pedido de venda,

O sistema não deve permitir que o campo "Quantidade" seja inserido com valor maior que: o campo lote.quantidade do lote selecionado no item do pedido subtraído das movimentações negativas de lote ativas e não processadas, valor definido pela select a seguir:

        
            SELECT l.quantidade - (SELECT SUM(lm.quantidade) FROM lotemovimento lm WHERE lm.idlote = l.idlote AND
            lm.idnativo = 1 AND lm.idnprocessado = 0 AND lm.quantidade < 0) FROM lote l WHERE idlote = ${lote_selecionado_no_item}
        
    

Ao finalizar o pedido, o sistema deve persistir uma movimentação negativa de movimentação de lote com os seguintes valores:

  • idlotemovimento: nextval("seqpklotemovimento")
  • idlote: ${id_do_lote_selecionado_no_item}
  • quantidade: pedidoproduto.quantidade WHERE idpedidoproduto = ${id_do_pedidoproduto}
  • idnativo: 1
  • idnprocessado: 0
  • idpedidoproduto: ${id_do_pedidoproduto}

Processamento de Movimentações de Lote Pela Integração

Semelhantemente à documentação Processamento de movimentos de cota por integração, o sistema deve possuir serviço de integração comum que processa movimentações de lote, em função de status de pedidos.

Sendo assim:

Inserir na tabela wsconfigintegracao:

        
            INSERT INTO public.wsconfigintegracao
            (erp, contexto, descricao, tabela, campo, valor, idnativo)
            VALUES
            ('COMUM', 'LOTE', 'Parâmetro que define os status de pedidos que terão seus movimentos de lote processados pela integração automaticamente. Valores podem ser separados por vírgula',
            'processamovimento', 'sgltiposituacaopedido', 'PF', 1);
            INSERT INTO public.wsconfigintegracao
            (erp, contexto, descricao, tabela, campo, valor, idnativo)
            VALUES
            ('COMUM', 'LOTE', 'Parâmetro que define os status de pedidos que terão seus movimentos de lote inativados pela integração automaticamente. Valores podem ser separados por vírgula',
            'inativamovimento', 'sgltiposituacaopedido', 'PC', 1);
        
    

O serviço de processamento de lote deverá:

Consultar quais são as movimentações de lotes ativas e não processadas de pedidos que possuem status dentro do definido pelo parâmetro processamovimento.

        
            SELECT * FROM lotemovimento ccm
            INNER JOIN pedido p ON p.idpedido = ccm.idpedido
            WHERE p.idtiposituacaopedido IN
            (SELECT idtiposituacaopedido FROM tiposituacaopedido WHERE sgltiposituacaopedido IN (${parâmetro_processamovimento}))
            AND ccm.idnativo = 1 AND ccm.idnprocessado = 0
        
    

Com esses movimentos no fluxo, a integração deverá processar o movimento, com o seguinte update:

        
            UPDATE lotemovimento SET idnprocessado = 1 WHERE idlotemovimento IN (${consulta_1})
        
    

Após o processamento dos lotes acima, a integração deverá atualizar a quantidade de lote com o valor que foi recém processado, segundo:

        
            UPDATE lote SET quantidade = quantidade + ${movimento_processado}
        
    

O serviço de inativação de lote deverá:

Consultar quais são as movimentações de lote não processadas de pedidos que possuem status dentro do definido pelo parâmetro inativamovimento.

        
            SELECT * FROM lotemovimento ccm
            INNER JOIN pedido p ON p.idpedido = ccm.idpedido
            WHERE p.idtiposituacaopedido IN
            (SELECT idtiposituacaopedido FROM tiposituacaopedido WHERE sgltiposituacaopedido IN (${parâmetro_inativamovimento}))
            AND ccm.idnativo = 1 AND ccm.idnprocessado = 0
        
    

Com esses movimentos no fluxo, a integração deverá processar o movimento, com o seguinte update:

        
            UPDATE lotemovimento SET idnativo = 0 WHERE idlotemovimento IN (${consulta_2})
        
    

PERGUNTAS FREQUENTES

  • question_answerÉ possível remover apenas um item específico de uma campanha de produtos?
    Não, o objetivo principal de uma campanha de produtos é promover a venda do combo ou conjunto específico de produtos oferecido.