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
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.
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.
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
Boa!! Que bom que ajudou!
Pingback: Oracle EBS – Liberando Retenções – API do Oracle (OE_HOLDS_PUB.Release_Holds) – Fragmentoweb