EBS – Liberando Retenções – API do Oracle (OE_HOLDS_PUB.Release_Holds)

Fala galera!

Esse é mais um dos meus clássicos posts sobre APIs do Oracle. Chamei de clássicos pois não é o primeiro, hahá! Acho que é o segundo sobre APIs. Um clássico.

Enfim, hoje vamos ver uma API que já utilizei em muitos lugares onde trabalhei, pois sempre existe a necessidade de aplicar e/ou remover alguma retenção em alguns pedidos, de forma automática e através de customização.

Neste post vou abordar apenas como remover a retenção, usando a API abaixo:

-- Faz a chamada da API para liberação das retenções
OE_HOLDS_PUB.Release_Holds(p_api_version       => 1.0
                         , p_init_msg_list     => FND_API.G_TRUE
                         , p_commit            => FND_API.G_FALSE
                         , p_validation_level  => FND_API.G_VALID_LEVEL_NONE
                         , p_hold_source_rec   => r_hold_source_rec
                         , p_hold_release_rec  => r_hold_release_rec
                         , x_return_status     => w_return_status
                         , x_msg_count         => w_msg_count
                         , x_msg_data          => w_msg_data);

A Api é bem simples de usar. Para ficar ainda mais fácil, criei um script pronto para rodar, bastando apenas informar qual é o pedido. O programa irá buscar todas as retenções que o pedido possui e irá liberar uma por uma.

No exemplo, foi necessário setar o contexto para que funcione corretamente ao rodar fora do ambiente do EBS, inclusive tendo que setar, além da organização, também a responsabilidade e usuário logado. Conforme abaixo:

fnd_global.apps_initialize(15992, 50663, 660);
mo_global.set_policy_context(p_access_mode => 'S', p_org_id => 81);

Porém quando rodando dentro do EBS, não precisa nada disso acima.

Segue abaixo o código fonte do exemplo:

DECLARE
  
  w_return_status VARCHAR2(1);
  w_message_error VARCHAR2(4000);

  -------------------------------------------------------------------
  -- Gera um log no concorrente 
  -------------------------------------------------------------------
  PROCEDURE gera_log(p_log IN VARCHAR2) IS
  BEGIN
    --Fnd_File.Put_Line(Fnd_File.Output, to_char(SYSDATE, 'DD/MM/RRRR HH24:MI:SS')||': '||p_log);
    dbms_output.put_line(to_char(SYSDATE, 'DD/MM/RRRR HH24:MI:SS')||': '||p_log);
  END gera_log;

  -------------------------------------------------------------------
  -- Libera todas as retenções de uma Ordem, caso a ordem possua
  -- origem como SALDO OP
  -------------------------------------------------------------------
  PROCEDURE Libera_Retencoes_Pedido(p_header_id      IN NUMBER
                                  , x_return_status OUT VARCHAR2
                                  , x_message_error OUT VARCHAR2) IS
    
    -- Busca informações do pedido
    CURSOR c_header IS
    SELECT oeoh.order_number
         , oeos.name order_source_name
      FROM oe_order_headers_all oeoh
         , oe_order_sources     oeos
     WHERE oeoh.order_source_id = oeos.order_source_id
       AND oeoh.header_id       = p_header_id;
    
    -- Busca todas as retenções do pedido
    CURSOR c_holds IS
    SELECT hd.hold_id
         , hs.hold_entity_code
         , oh.header_id
         , hs.hold_source_id
         , hd.name hold_name
      FROM oe_order_holds_all  oh
         , oe_hold_sources_all hs
         , oe_hold_definitions hd
     WHERE oh.hold_source_id = hs.hold_source_id
       AND hs.hold_id        = hd.hold_id
       AND oh.released_flag  = 'N'
       AND oh.line_id        IS NULL
       AND oh.header_id      = p_header_id;
    
    r_header            c_header%ROWTYPE;
    r_hold_source_rec   OE_HOLDS_PVT.HOLD_SOURCE_REC_TYPE;
    r_hold_release_rec  OE_HOLDS_PVT.HOLD_RELEASE_REC_TYPE;
    w_count             NUMBER;
    
    w_return_status     VARCHAR2(1);
    w_msg_count         NUMBER;
    w_msg_data          VARCHAR2(32767);
    w_index             BINARY_INTEGER;
    
    E_ERROR             EXCEPTION;
    
  BEGIN
    
    x_return_status := 'S';
    x_message_error := NULL;
  
    -- Busca informações do pedido
    OPEN c_header;
    FETCH c_header INTO r_header;
    CLOSE c_header;
    
    -- Verifica se o pedido foi encontrado
    IF r_header.order_number IS NULL THEN
      x_return_status := 'E';
      x_message_error := 'Pedido com #ID '||p_header_id||' não foi encontrado';
      RETURN;
    END IF;
  
    -- Verifica se o pedido é elegível para o processo
    IF r_header.order_source_name != 'SALDO OP' THEN
      x_return_status := 'E';
      x_message_error := 'Pedido deve possuir origem "SALDO OP". O pedido informado ('||r_header.order_number||') possui origem "'||r_header.order_source_name||'"';
      RETURN;
    END IF;
    
    gera_log(RPAD('-', 100, '-'));
    gera_log('Iniciando processo de liberação de retenções para o pedido '||r_header.order_number);
    gera_log(RPAD('-', 100, '-'));
    
    w_count := 0;
    -- Percorre todas as retenções do pedido e libera todas elas
    FOR r_hold IN c_holds LOOP

      w_count := w_count + 1;
      
      BEGIN
        
        r_hold_source_rec := NULL;
        r_hold_source_rec.hold_id              := r_hold.hold_id;
        r_hold_source_rec.hold_entity_code     := r_hold.hold_entity_code;
        r_hold_source_rec.hold_entity_id       := r_hold.header_id;
        --
        r_hold_release_rec := NULL;
        r_hold_release_rec.hold_source_id      := r_hold.hold_source_id;
        r_hold_release_rec.release_reason_code := 'VALID_CONFIG'; -- FIXO
        r_hold_release_rec.release_comment     := 'Liberado pois SALDO OP não deve ter retenções aplicadas';
        
        gera_log('Liberando Retenção "'||r_hold.hold_name||'"');
        
        OE_MSG_PUB.Initialize ();
        
        -- Faz a chamada da API para liberação das retenções
        OE_HOLDS_PUB.Release_Holds(p_api_version       => 1.0
                                 , p_init_msg_list     => FND_API.G_TRUE
                                 , p_commit            => FND_API.G_FALSE
                                 , p_validation_level  => FND_API.G_VALID_LEVEL_NONE
                                 , p_hold_source_rec   => r_hold_source_rec
                                 , p_hold_release_rec  => r_hold_release_rec
                                 , x_return_status     => w_return_status
                                 , x_msg_count         => w_msg_count
                                 , x_msg_data          => w_msg_data);

        -- Verifica se a retencao foi liberada
        IF w_return_status = FND_API.G_RET_STS_SUCCESS THEN
          gera_log('  -> Retenção "'||r_hold.hold_name||'" liberada com sucesso');
        ELSE
          
          x_return_status := 'E';
          x_message_error := 'Erro ao liberar retenção "'||r_hold.hold_name||'" do Pedido "'||r_header.order_number||'". Erro ('||w_msg_count||'): ';
          
          gera_log('  -> '||x_message_error);
          
          -- Busca mensagens de erro
          IF w_msg_count > 0 THEN
            FOR w_index IN 1..w_msg_count LOOP
              w_msg_data := OE_MSG_PUB.get(p_msg_index => w_index
                                         , p_encoded   => 'F');
              
              gera_log('  -> '||w_index||' - '||w_msg_data);
              
              -- Valida para nao estourar o campo
              IF Length(x_message_error||w_msg_data) <= 4000 THEN
                x_message_error := x_message_error || w_msg_data;
              END IF;

            END LOOP;
          END IF;
          
          RAISE E_ERROR;
        END IF;
        
      EXCEPTION
        WHEN E_ERROR THEN
          RAISE E_ERROR;
        WHEN OTHERS THEN
          x_return_status := 'E';
          x_message_error := 'Erro ao liberar retenção "'||r_hold.hold_name||'" do Pedido "'||r_header.order_number||'". Erro: '||SQLERRM;
          gera_log(x_message_error);
          RAISE E_ERROR;
      END;
    
    END LOOP;
    
    gera_log(RPAD('-', 100, '-'));
    IF w_count > 0 THEN
      COMMIT;
      gera_log('Liberadas '||w_count||' retenções para o pedido "'||r_header.order_number||'"');
    ELSE
      gera_log('Nenhuma retenção encontrada para o pedido "'||r_header.order_number||'"');
    END IF;
    
  EXCEPTION
    WHEN E_ERROR THEN
      ROLLBACK;
    WHEN OTHERS THEN
      x_return_status := 'E';
      x_message_error := 'Erro ao liberar retenções do Pedido com #ID '||p_header_id||'. Erro: '||SQLERRM;
  END Libera_Retencoes_Pedido;
  
BEGIN
  
  -- IMPORTANTE APENAS QUANDO RODANDO FORA DO EBS
  fnd_global.apps_initialize(15992, 50663, 660);
  mo_global.set_policy_context(p_access_mode => 'S', p_org_id => 81);
  --
 
  -- Libera todas as retenções do pedido
  Libera_Retencoes_Pedido(p_header_id     => 2748543 -- HEADER_ID do Pedido
                        , x_return_status => w_return_status
                        , x_message_error => w_message_error);
  
  IF w_return_status != 'S' THEN
    gera_log(RPAD('-', 100, '-'));
    gera_log('FINALIZADO COM ERRO: '||w_message_error);
  END IF;
  
END;

Se foi útil, ou se você apenas gostou, peço que compartilhe com seus contatos, poderá ser muito útil para eles.
Qualquer dúvida comenta aqui no blog.

Grande Abraço

5 thoughts on “EBS – Liberando Retenções – API do Oracle (OE_HOLDS_PUB.Release_Holds)

  1. Fernando Arcoverde Analista de Sistemas Reply

    Depois vou precisar do seu help também para “aplicar um hold” automaticamente, vis script…. rs
    Se puder me contatar pelo e-mail, te agradeço.

    • Genilto Vanzin Post authorReply

      Opa, faz um certo tempo que não mexo mais muito com EBS. Mas se puder ajudar irei. Manda tua dúvida lá no contato do site mesmo que respondo o email.

  2. Fernando Arcoverde Analista de Sistemas Reply

    Genilto, muito obrigado.
    Você salvou a minha vida !!!! rs
    Parabéns.
    Conhecia a API mas não sabia muito bem como usá-la.
    O seu script foi 1000

    Parabens e mais uma vez Muito Obrigado pelo seu post

  3. Pingback: Oracle EBS – Liberando Retenções – API do Oracle (OE_HOLDS_PUB.Release_Holds) – Fragmentoweb

Leave a Reply

Your email address will not be published. Required fields are marked *