Este é um post originalmente do site genilto.com. Como é de nosso enorme interesse, faremos uma republicação aqui!
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
