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