這篇文章主要講解了“API怎么實現批次序列號的銷售出庫”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“API怎么實現批次序列號的銷售出庫”吧!
成都創(chuàng)新互聯從2013年開始,是專業(yè)互聯網技術服務公司,擁有項目網站建設、成都網站設計網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元右玉做網站,已為上家服務,為右玉各地企業(yè)和個人服務,聯系電話:18980820575
隨著制造企業(yè)對生產銷售的控制越來越高,越來越多的制造型企業(yè)增加了對物料的批次、序列號的控制。我們可以在庫存職責中的:物料 –> 主組織物料/組織產品 -> 庫存TAB頁:來這只某個庫存組織中是否啟用序列或者是批次。
啟用物料的批次、序列控制后,該無聊在采購入庫、銷售出庫都需要填寫相應有效批次序列。
在Ebs中我們經常會碰到要實現自動化的公司間事務處理,比如自動銷售出庫,自動的采購入庫。本文就將講解如何實現帶序列號、批次控制的銷售出庫。
在Ebs的界面上手工的進行銷售出庫,我們是去修改物料搬運單的屬性,物料搬運單 -> 處理物料搬運單 -> 處理物料搬運單分配。如果啟用序列、批次號控制,“序列/批次”按鈕將會亮起來。
既然實在處理物料搬運單時修改的批次、序列,我們首先就會想到物料搬運單的API來實現這個功能:(挑庫確認之前)可使用的API有:
? INV_MOVE_ORDER_PUB.Process_Move_Order
? INV_MOVE_ORDER_PUB.Process_Move_Order_Line
該API中的p_trolin_tbl(i).lot_number、p_trolin_tbl(i).serial_number_start、p_trolin_tbl(i).serial_number_end是允許設置和修改。但是讓人失望的是,雖然修改了但是挑庫發(fā)運卻看不出任何效果,發(fā)出去的物料根本就不是我們指定的批次和序列。
這是因為,庫存事務處理是根據下面三個表中的數據進行處理的,而不是根據物料搬運單行。
? MTL_MATERIAL_TRANSACTIONS_TEMP (庫存事務處理臨時表)
? MTL_TRANSACTION_LOTS_TEMP (批次臨時表)
? MTL_SERIAL_NUMBERS_TEMP (序列號臨時表)
然而這三個表 Oracle 并沒有提供API來修改它們。
那么我們想:既然是臨時表,為何不直接UPDATE它們?那么我們就試一試。
處理步驟:
1. 創(chuàng)建銷售訂單
2. 挑庫發(fā)放(非自動確認)
3. 使用INV_MOVE_ORDER_PUB.Process_Move_Order_Line修改物料搬運單行
4. 更新MMT、MLT、MST表中的相關數據
5. 挑庫確認
6. 發(fā)運確認
如果你的版本是12.1以后,那么發(fā)運過程中的請求將會報錯,ERROR_CODE:Serial Mssing(序列號控制的情況下出現,批次中不會出現,MetaLink補丁解決這個BUG)。
但是不管怎么樣,去直接UPDATE一個表總讓人覺得不好(而且還有BUG),那么如果辦呢?
我們可以使用一個Oracle未公開的API來覺得這個問題:inv_replenish_detail_pub.line_details_pub.
跳出開始的固定思維,既然Oracle沒有API(包括未公開的)去修改物料搬運單的序列和批次,為什么我們不直接做出來一個符合我們要求的物料搬運單呢?
下面給出一個銷售訂單自動事務處理的API方案:
1. oe_order_pub.process_order 創(chuàng)建銷售訂單.
2. wsh_picking_batches_pub.Create_Batch 創(chuàng)建批次號(自動確認:否/自動分配:否).
3. wsh_picking_batches_pub.Release_Batch發(fā)放銷售訂單(并發(fā),ONLINE都行).
4. INV_Trolin_Util.Query_Rows 獲取物料搬運單行
5. INV_MOVE_ORDER_PUB.Process_Move_Order_Line
修改物料搬運單行(頭上的發(fā)出子庫無需修改).
6. inv_replenish_detail_pub.line_details_pub
創(chuàng)建物料搬運單分配行(注1)
7. inv_pick_wave_pick_confirm_pub.pick_confirm
挑庫確認
8. wsh_deliveries_pub.delivery_action 交貨號發(fā)運
9. wsh_ship_confirm_actions.interface_all 發(fā)運確認
注1:如果挑庫發(fā)放因為業(yè)務需求的原因不能這是自動分配:否,或者由于其他原因在此處已經有了物料搬運單行的分配行,那么請使用API
inv_mo_line_detail_util.reduce_allocation_quantity
來刪除配分行(當減小數量等于發(fā)運的數量時,事務處理行將被刪除)。
下面給出修改物料搬運單行,重新生成分配的單行代碼的調用示例:
[java] view plain copy
DECLARE
-- Common Declarations
l_api_version NUMBER := 1.0;
l_init_msg_list VARCHAR2(2) := FND_API.G_TRUE;
l_return_values VARCHAR2(2) := FND_API.G_FALSE;
l_commit VARCHAR2(2) := FND_API.G_FALSE;
x_return_status VARCHAR2(2);
x_msg_count NUMBER := ;
x_msg_data VARCHAR2(255);
-- API specific declarations
l_header_id NUMBER := ;
l_trohdr_rec INV_MOVE_ORDER_PUB.TROHDR_REC_TYPE;
l_trohdr_val_rec INV_MOVE_ORDER_PUB.TROHDR_VAL_REC_TYPE;
l_trolin_tbl INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;
o_trolin_tbl INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;
l_trolin_val_tbl INV_MOVE_ORDER_PUB.TROLIN_VAL_TBL_TYPE;
x_trolin_tbl INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;
x_trolin_val_tbl INV_MOVE_ORDER_PUB.TROLIN_VAL_TBL_TYPE;
x_trohdr_rec INV_MOVE_ORDER_PUB.TROHDR_REC_TYPE;
x_trohdr_val_rec INV_MOVE_ORDER_PUB.TROHDR_VAL_REC_TYPE;
-- Cursor to load Move Order Headers
l_mold_tbl INV_MO_LINE_DETAIL_UTIL.g_mmtt_tbl_type;
x_mold_tbl INV_MO_LINE_DETAIL_UTIL.g_mmtt_tbl_type;
l_move_order_type NUMBER := 3;
l_msg_return NUMBER;
x_number_of_rows NUMBER ;
x_detailed_qty NUMBER ;
x_revision VARCHAR2(20) ;
x_locator_id NUMBER ;
x_transfer_to_location NUMBER ;
x_lot_number VARCHAR2(80) ;
x_expiration_date DATE ;
x_transaction_temp_id NUMBER ;
p_transaction_header_id NUMBER ;
p_transaction_mode NUMBER ;
p_move_order_type NUMBER := 3;
p_serial_flag VARCHAR2(1) ;
p_plan_tasks BOOLEAN ;
p_auto_pick_confirm BOOLEAN ;
p_commit BOOLEAN ;
l_t_header_id NUMBER;
l_lot_number VARCHAR2(80) := 'SLT0021'; --mtl_lot_numbers.lot_number;
l_serial_number VARCHAR2(20) := '3.06.S0019'; --mtl_serial_numbers.serial_number
l_subinvetory_code VARCHAR2(10) := 'BJJF_CLK'; --mtl_secondary_inventories.secondary_inventory_name
l_locator_id NUMBER := 42; --mtl_item_locations.inventory_location_id
l_trx_header_id NUMBER := 93023; --mtl_txn_request_headers.header_id
BEGIN
FND_GLOBAL.APPS_INITIALIZE(1371, 50627, 660); -- Suhasini / Mfg Mgr / INV
INV_MOVE_ORDER_PUB.Get_Move_Order(
P_API_VERSION_NUMBER => l_api_version
, P_INIT_MSG_LIST => l_init_msg_list
, P_RETURN_VALUES => l_return_values
, X_RETURN_STATUS => x_return_status
, X_MSG_COUNT => x_msg_count
, X_MSG_DATA => x_msg_data
, P_HEADER_ID => l_trx_header_id--93023
, P_HEADER => NULL
, X_TROHDR_REC => l_trohdr_rec
, X_TROHDR_VAL_REC => l_trohdr_val_rec
, X_TROLIN_TBL => l_trolin_tbl
, X_TROLIN_VAL_TBL => l_trolin_val_tbl
);
-- Print the Move Order Header/Lines to be processed
IF (x_return_status = FND_API.G_RET_STS_SUCCESS) THEN
l_trohdr_rec.operation := INV_GLOBALS.G_OPR_UPDATE;
-- FOR i IN 1..l_trolin_tbl.COUNT LOOP
l_trolin_tbl(1).from_subinventory_code := l_subinvetory_code;
l_trolin_tbl(1).from_locator_id := l_locator_id;
l_trolin_tb1(i).lot_number := l_lot_number;
l_trolin_tbl(1).serial_number_start := l_serial_number;
l_trolin_tbl(1).serial_number_end := l_serial_number;
l_trolin_tbl(1).attribute1 := 'update move order test!';
l_trolin_tbl(1).operation := INV_GLOBALS.G_OPR_UPDATE;
-- END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Get_Move_Order error!');
RETURN;
END IF;
INV_MOVE_ORDER_PUB.Process_Move_Order_Line( p_api_version_number => 1.0
,p_init_msg_list => l_init_msg_list
,p_return_values => l_return_values
,p_commit => l_commit
,x_return_status => x_return_status
,x_msg_count => x_msg_count
,x_msg_data => x_msg_data
,p_trolin_tbl => l_trolin_tbl
,p_trolin_old_tbl => l_trolin_tbl
,x_trolin_tbl => x_trolin_tbl);
IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
FOR i IN 1..x_msg_count LOOP
fnd_msg_pub.get(p_msg_index => i
,p_encoded => 'F'
,p_data => x_msg_data
,p_msg_index_out => l_msg_return);
DBMS_OUTPUT.PUT_LINE(x_msg_data);
END LOOP;
RETURN;
ELSE
DBMS_OUTPUT.PUT_LINE('MODIFY SUCESS!');
END IF;
/* inv_mo_line_detail_util.reduce_allocation_quantity(
x_return_status => x_return_status
,p_transaction_temp_id => 2242994
,p_quantity => 1
,p_secondary_quantity => 1) ;
IF x_return_status <> 'S' THEN
DBMS_OUTPUT.PUT_LINE('EE');
ELSE
DBMS_OUTPUT.PUT_LINE('SS');
END IF;*/
inv_replenish_detail_pub.line_details_pub(
p_line_id => l_trolin_tbl(1).line_id
, x_number_of_rows => x_number_of_rows
, x_detailed_qty => x_detailed_qty
, x_return_status => x_return_status
, x_msg_count => x_msg_count
, x_msg_data => x_msg_data
, x_revision => x_revision
, x_locator_id => x_locator_id
, x_transfer_to_location => x_transfer_to_location
, x_lot_number => x_lot_number
, x_expiration_date => x_expiration_date
, x_transaction_temp_id => x_transaction_temp_id
, p_transaction_header_id => NULL
, p_transaction_mode => NULL
, p_move_order_type => p_move_order_type
, p_serial_flag => FND_API.G_FALSE
, p_plan_tasks => FALSE
, p_auto_pick_confirm => FALSE
, p_commit => FALSE);
IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
DBMS_OUTPUT.PUT_LINE('E');
FOR i IN 1..x_msg_count LOOP
fnd_msg_pub.get(p_msg_index => i
,p_encoded => 'F'
,p_data => x_msg_data
,p_msg_index_out => l_msg_return);
DBMS_OUTPUT.PUT_LINE(x_msg_data);
END LOOP;
RETURN;
ELSE
DBMS_OUTPUT.PUT_LINE('ssssss');
DBMS_OUTPUT.PUT_LINE('x_number_of_rows: ' || to_char(x_number_of_rows));
DBMS_OUTPUT.PUT_LINE('x_locator_id: ' || to_char(x_locator_id));
DBMS_OUTPUT.PUT_LINE('x_lot_number: ' || to_char(x_lot_number));
DBMS_OUTPUT.PUT_LINE('x_transfer_to_location: ' || to_char(x_transfer_to_location));
DBMS_OUTPUT.PUT_LINE('x_transaction_temp_id: ' || to_char(x_transaction_temp_id));
END IF;
l_trolin_tbl := INV_Trolin_Util.Query_Rows(p_line_id => l_trolin_tbl(1).line_id);
l_mold_tbl := INV_MO_LINE_DETAIL_UTIL.query_rows(p_line_id => l_trolin_tbl(1).line_id);
INV_PICK_WAVE_PICK_CONFIRM_PUB.Pick_Confirm(p_api_version_number => l_api_version,
p_init_msg_list => l_init_msg_list,
p_commit => l_commit,
x_return_status => x_return_status,
x_msg_count => x_msg_count,
x_msg_data => x_msg_data,
p_move_order_type => l_move_order_type,
p_transaction_mode => 1,
p_trolin_tbl => l_trolin_tbl,
p_mold_tbl => l_mold_tbl,
x_mmtt_tbl => x_mold_tbl,
x_trolin_tbl => x_trolin_tbl);
IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
DBMS_OUTPUT.PUT_LINE('E');
FOR i IN 1..x_msg_count LOOP
fnd_msg_pub.get(p_msg_index => i
,p_encoded => 'F'
,p_data => x_msg_data
,p_msg_index_out => l_msg_return);
DBMS_OUTPUT.PUT_LINE(x_msg_data);
END LOOP;
RETURN;
ELSE
DBMS_OUTPUT.PUT_LINE('S');
END IF;
-- END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE ||':'||SQLERRM);
END;
有可能業(yè)務上只需要在發(fā)運出庫的時候在交貨號顯示序列號和批次號,但是實際庫存控制并沒有這個需求,也可以在挑庫確認后,通過API來修改交貨號的屬性來達到顯示序列號和批次號的目的:wsh_delivery_details_pub.Update_Shipping_Attributes
但是這個并不能達到實際出庫控制的效果
下面也給出一個示例:
DECLARE
--這只是一個取數的例子,修改成別的取數邏輯,
--cux開頭的是客戶化的表
CURSOR dev_header_cur(p_item_key VARCHAR2) IS
SELECT
wdd.source_header_id AS source_header_id
,wdd.source_header_number AS source_header_number
,wdd.source_line_id AS source_line_id
,wda.delivery_id AS delivery_id
,wdd.delivery_detail_id AS delivery_detail_id
,wdd.organization_id AS organization_id
,wdd.source_code AS source_code
,wdd.requested_quantity AS requested_quantity
,tll.batch_number AS lot_number
,tll.sequence_number AS serial_number
,tll.line_number AS line_number
,tll.header_id AS load_header_id
,tll.line_id AS load_line_id
,tll.send_sec_inv_code AS send_subinventory
,tll.send_inv_location_id AS send_locator_id
FROM
cux_tr_load_doc_wf_headers cwh
,cux_tr_load_doc_wf_lines cwl
,cux_tr_load_doc_lines_all tll
,oe_order_headers_all ooh
,oe_order_lines_all ool
,wsh_delivery_details wdd
,wsh_delivery_assignments wda
WHERE
cwh.l_inner_oe_header_id = ooh.header_id
AND cwh.header_id = cwl.header_id
AND cwl.load_doc_line_id = tll.line_id
AND cwl.l_inner_oe_line_id = ool.line_id
AND ool.line_id = wdd.source_line_id --bug fix 2010-08-19
AND wdd.delivery_detail_id = wda.delivery_detail_id
--
-- the value of parameter
--
AND cwh.item_key = 'STH001';
l_index NUMBER;
l_msg_return NUMBER;
x_return_status VARCHAR2(1);
x_msg_count NUMBER;
x_msg_data VARCHAR2(2000);
l_source_code VARCHAR2(40);
l_serialrangetabtype wsh_glbl_var_strct_grp.ddserialrangetabtype;
l_changedattributetabtype wsh_delivery_details_pub.changedattributetabtype;
BEGIN
fnd_global.APPS_INITIALIZE( user_id => -1
,resp_id => -1
,resp_appl_id => -1);
l_index := ;
FOR dev_header_rec IN dev_header_cur('STH001') LOOP
l_index := l_index + 1;
l_source_code := dev_header_rec.source_code;
l_changedattributetabtype(l_index).source_header_id := dev_header_rec.source_header_id;
l_changedattributetabtype(l_index).source_line_id := dev_header_rec.source_line_id;
l_changedattributetabtype(l_index).delivery_detail_id := dev_header_rec.delivery_detail_id;
l_changedattributetabtype(l_index).subinventory := 'CLK_SD';
l_changedattributetabtype(l_index).locator_id := 42;--貨位控制
l_changedattributetabtype(l_index).lot_number := 'LOT_SK001';--批次
IF dev_header_rec.requested_quantity = 1 THEN
l_changedattributetabtype(l_index).serial_number := 'LEOCHEN194';
END IF;
FOR i IN 1..dev_header_rec.requested_quantity LOOP
l_serialrangetabtype(1).delivery_detail_id := dev_header_rec.delivery_detail_id;
l_serialrangetabtype(1).from_serial_number := 'LEOCHEN194';--LEOCHEN165
l_serialrangetabtype(1).to_serial_number := 'LEOCHEN194';
--v_serialRangeTabType(1).quantity := 1; --Dl.ordered_qty;
l_serialrangetabtype(2).delivery_detail_id := dev_header_rec.delivery_detail_id;
l_serialrangetabtype(2).from_serial_number := 'LEOCHEN195';--LEOCHEN165
l_serialrangetabtype(2).to_serial_number := 'LEOCHEN195';
--......在此設置多個序列號在一行的情況
END LOOP;
END LOOP;
wsh_delivery_details_pub.Update_Shipping_Attributes(p_api_version_number => 1.0,
p_init_msg_list => FND_API.G_FALSE,
p_commit => FND_API.G_FALSE,
x_return_status => x_return_status,
x_msg_count => x_msg_count,
x_msg_data => x_msg_data,
p_changed_attributes => l_changedattributetabtype,
p_source_code => l_source_code,
p_container_flag => NULL ,
p_serial_range_tab => l_serialrangetabtype );
IF x_return_status <> fnd_api.G_RET_STS_SUCCESS THEN
FOR i IN 1..x_msg_count LOOP
fnd_msg_pub.get(p_msg_index => i
,p_encoded => 'F'
,p_data => x_msg_data
,p_msg_index_out => l_msg_return);
dbms_output.put_line(x_msg_data);
END LOOP;
ELSE
dbms_output.put_line('S');
END IF;
END;
感謝各位的閱讀,以上就是“API怎么實現批次序列號的銷售出庫”的內容了,經過本文的學習后,相信大家對API怎么實現批次序列號的銷售出庫這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯,小編將為大家推送更多相關知識點的文章,歡迎關注!