千家信息网

API怎么实现批次序列号的销售出库

发表于:2024-12-12 作者:千家信息网编辑
千家信息网最后更新 2024年12月12日,这篇文章主要讲解了"API怎么实现批次序列号的销售出库",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"API怎么实现批次序列号的销售出库"吧!随着制造企
千家信息网最后更新 2024年12月12日API怎么实现批次序列号的销售出库

这篇文章主要讲解了"API怎么实现批次序列号的销售出库",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"API怎么实现批次序列号的销售出库"吧!

随着制造企业对生产销售的控制越来越高,越来越多的制造型企业增加了对物料的批次、序列号的控制。我们可以在库存职责中的:物料 -> 主组织物料/组织产品 -> 库存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是允许设置和修改。但是让人失望的是,虽然修改了但是挑库发运却看不出任何效果,发出去的物料根本就不是我们指定的批次和序列。

这是因为,库存事务处理是根据下面三个表中的数据进行处理的,而不是根据物料搬运单行。

Ø MTL_MATERIAL_TRANSACTIONS_TEMP (库存事务处理临时表)

Ø MTL_TRANSACTION_LOTS_TEMP (批次临时表)

Ø MTL_SERIAL_NUMBERS_TEMP (序列号临时表)

然而这三个表 Oracle 并没有提供API来修改它们。

那么我们想:既然是临时表,为何不直接UPDATE它们?那么我们就试一试。

处理步骤:

1. 创建销售订单

2. 挑库发放(非自动确认)

3. 使用INV_MOVE_ORDER_PUB.Process_Move_Order_Line修改物料搬运单行

4. 更新MMT、MLT、MST表中的相关数据

5. 挑库确认

6. 发运确认

如果你的版本是12.1以后,那么发运过程中的请求将会报错,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 创建销售订单.

2. wsh_picking_batches_pub.Create_Batch 创建批次号(自动确认:否/自动分配:否).

3. wsh_picking_batches_pub.Release_Batch发放销售订单(并发,ONLINE都行).

4. INV_Trolin_Util.Query_Rows 获取物料搬运单行

5. INV_MOVE_ORDER_PUB.Process_Move_Order_Line

修改物料搬运单行(头上的发出子库无需修改).

6. inv_replenish_detail_pub.line_details_pub

创建物料搬运单分配行(注1)

7. inv_pick_wave_pick_confirm_pub.pick_confirm

挑库确认

8. wsh_deliveries_pub.delivery_action 交货号发运

9. wsh_ship_confirm_actions.interface_all 发运确认

注1:如果挑库发放因为业务需求的原因不能这是自动分配:否,或者由于其他原因在此处已经有了物料搬运单行的分配行,那么请使用API

inv_mo_line_detail_util.reduce_allocation_quantity

来删除配分行(当减小数量等于发运的数量时,事务处理行将被删除)。

下面给出修改物料搬运单行,重新生成分配的单行代码的调用示例:

[java] view plain copy

  1. DECLARE

  2. -- Common Declarations

  3. l_api_version NUMBER := 1.0;

  4. l_init_msg_list VARCHAR2(2) := FND_API.G_TRUE;

  5. l_return_values VARCHAR2(2) := FND_API.G_FALSE;

  6. l_commit VARCHAR2(2) := FND_API.G_FALSE;

  7. x_return_status VARCHAR2(2);

  8. x_msg_count NUMBER := ;

  9. x_msg_data VARCHAR2(255);

  10. -- API specific declarations

  11. l_header_id NUMBER := ;

  12. l_trohdr_rec INV_MOVE_ORDER_PUB.TROHDR_REC_TYPE;

  13. l_trohdr_val_rec INV_MOVE_ORDER_PUB.TROHDR_VAL_REC_TYPE;

  14. l_trolin_tbl INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;

  15. o_trolin_tbl INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;

  16. l_trolin_val_tbl INV_MOVE_ORDER_PUB.TROLIN_VAL_TBL_TYPE;

  17. x_trolin_tbl INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;

  18. x_trolin_val_tbl INV_MOVE_ORDER_PUB.TROLIN_VAL_TBL_TYPE;

  19. x_trohdr_rec INV_MOVE_ORDER_PUB.TROHDR_REC_TYPE;

  20. x_trohdr_val_rec INV_MOVE_ORDER_PUB.TROHDR_VAL_REC_TYPE;

  21. -- Cursor to load Move Order Headers

  22. l_mold_tbl INV_MO_LINE_DETAIL_UTIL.g_mmtt_tbl_type;

  23. x_mold_tbl INV_MO_LINE_DETAIL_UTIL.g_mmtt_tbl_type;

  24. l_move_order_type NUMBER := 3;

  25. l_msg_return NUMBER;

  26. x_number_of_rows NUMBER ;

  27. x_detailed_qty NUMBER ;

  28. x_revision VARCHAR2(20) ;

  29. x_locator_id NUMBER ;

  30. x_transfer_to_location NUMBER ;

  31. x_lot_number VARCHAR2(80) ;

  32. x_expiration_date DATE ;

  33. x_transaction_temp_id NUMBER ;

  34. p_transaction_header_id NUMBER ;

  35. p_transaction_mode NUMBER ;

  36. p_move_order_type NUMBER := 3;

  37. p_serial_flag VARCHAR2(1) ;

  38. p_plan_tasks BOOLEAN ;

  39. p_auto_pick_confirm BOOLEAN ;

  40. p_commit BOOLEAN ;

  41. l_t_header_id NUMBER;

  42. l_lot_number VARCHAR2(80) := 'SLT0021'; --mtl_lot_numbers.lot_number;

  43. l_serial_number VARCHAR2(20) := '3.06.S0019'; --mtl_serial_numbers.serial_number

  44. l_subinvetory_code VARCHAR2(10) := 'BJJF_CLK'; --mtl_secondary_inventories.secondary_inventory_name

  45. l_locator_id NUMBER := 42; --mtl_item_locations.inventory_location_id

  46. l_trx_header_id NUMBER := 93023; --mtl_txn_request_headers.header_id

  47. BEGIN

  48. FND_GLOBAL.APPS_INITIALIZE(1371, 50627, 660); -- Suhasini / Mfg Mgr / INV

  49. INV_MOVE_ORDER_PUB.Get_Move_Order(

  50. P_API_VERSION_NUMBER => l_api_version

  51. , P_INIT_MSG_LIST => l_init_msg_list

  52. , P_RETURN_VALUES => l_return_values

  53. , X_RETURN_STATUS => x_return_status

  54. , X_MSG_COUNT => x_msg_count

  55. , X_MSG_DATA => x_msg_data

  56. , P_HEADER_ID => l_trx_header_id--93023

  57. , P_HEADER => NULL

  58. , X_TROHDR_REC => l_trohdr_rec

  59. , X_TROHDR_VAL_REC => l_trohdr_val_rec

  60. , X_TROLIN_TBL => l_trolin_tbl

  61. , X_TROLIN_VAL_TBL => l_trolin_val_tbl

  62. );

  63. -- Print the Move Order Header/Lines to be processed

  64. IF (x_return_status = FND_API.G_RET_STS_SUCCESS) THEN

  65. l_trohdr_rec.operation := INV_GLOBALS.G_OPR_UPDATE;

  66. -- FOR i IN 1..l_trolin_tbl.COUNT LOOP

  67. l_trolin_tbl(1).from_subinventory_code := l_subinvetory_code;

  68. l_trolin_tbl(1).from_locator_id := l_locator_id;

  69. l_trolin_tb1(i).lot_number := l_lot_number;

  70. l_trolin_tbl(1).serial_number_start := l_serial_number;

  71. l_trolin_tbl(1).serial_number_end := l_serial_number;

  72. l_trolin_tbl(1).attribute1 := 'update move order test!';

  73. l_trolin_tbl(1).operation := INV_GLOBALS.G_OPR_UPDATE;

  74. -- END LOOP;

  75. ELSE

  76. DBMS_OUTPUT.PUT_LINE('Get_Move_Order error!');

  77. RETURN;

  78. END IF;

  79. INV_MOVE_ORDER_PUB.Process_Move_Order_Line( p_api_version_number => 1.0

  80. ,p_init_msg_list => l_init_msg_list

  81. ,p_return_values => l_return_values

  82. ,p_commit => l_commit

  83. ,x_return_status => x_return_status

  84. ,x_msg_count => x_msg_count

  85. ,x_msg_data => x_msg_data

  86. ,p_trolin_tbl => l_trolin_tbl

  87. ,p_trolin_old_tbl => l_trolin_tbl

  88. ,x_trolin_tbl => x_trolin_tbl);

  89. IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN

  90. FOR i IN 1..x_msg_count LOOP

  91. fnd_msg_pub.get(p_msg_index => i

  92. ,p_encoded => 'F'

  93. ,p_data => x_msg_data

  94. ,p_msg_index_out => l_msg_return);

  95. DBMS_OUTPUT.PUT_LINE(x_msg_data);

  96. END LOOP;

  97. RETURN;

  98. ELSE

  99. DBMS_OUTPUT.PUT_LINE('MODIFY SUCESS!');

  100. END IF;

  101. /* inv_mo_line_detail_util.reduce_allocation_quantity(

  102. x_return_status => x_return_status

  103. ,p_transaction_temp_id => 2242994

  104. ,p_quantity => 1

  105. ,p_secondary_quantity => 1) ;

  106. IF x_return_status <> 'S' THEN

  107. DBMS_OUTPUT.PUT_LINE('EE');

  108. ELSE

  109. DBMS_OUTPUT.PUT_LINE('SS');

  110. END IF;*/

  111. inv_replenish_detail_pub.line_details_pub(

  112. p_line_id => l_trolin_tbl(1).line_id

  113. , x_number_of_rows => x_number_of_rows

  114. , x_detailed_qty => x_detailed_qty

  115. , x_return_status => x_return_status

  116. , x_msg_count => x_msg_count

  117. , x_msg_data => x_msg_data

  118. , x_revision => x_revision

  119. , x_locator_id => x_locator_id

  120. , x_transfer_to_location => x_transfer_to_location

  121. , x_lot_number => x_lot_number

  122. , x_expiration_date => x_expiration_date

  123. , x_transaction_temp_id => x_transaction_temp_id

  124. , p_transaction_header_id => NULL

  125. , p_transaction_mode => NULL

  126. , p_move_order_type => p_move_order_type

  127. , p_serial_flag => FND_API.G_FALSE

  128. , p_plan_tasks => FALSE

  129. , p_auto_pick_confirm => FALSE

  130. , p_commit => FALSE);

  131. IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN

  132. DBMS_OUTPUT.PUT_LINE('E');

  133. FOR i IN 1..x_msg_count LOOP

  134. fnd_msg_pub.get(p_msg_index => i

  135. ,p_encoded => 'F'

  136. ,p_data => x_msg_data

  137. ,p_msg_index_out => l_msg_return);

  138. DBMS_OUTPUT.PUT_LINE(x_msg_data);

  139. END LOOP;

  140. RETURN;

  141. ELSE

  142. DBMS_OUTPUT.PUT_LINE('ssssss');

  143. DBMS_OUTPUT.PUT_LINE('x_number_of_rows: ' || to_char(x_number_of_rows));

  144. DBMS_OUTPUT.PUT_LINE('x_locator_id: ' || to_char(x_locator_id));

  145. DBMS_OUTPUT.PUT_LINE('x_lot_number: ' || to_char(x_lot_number));

  146. DBMS_OUTPUT.PUT_LINE('x_transfer_to_location: ' || to_char(x_transfer_to_location));

  147. DBMS_OUTPUT.PUT_LINE('x_transaction_temp_id: ' || to_char(x_transaction_temp_id));

  148. END IF;

  149. l_trolin_tbl := INV_Trolin_Util.Query_Rows(p_line_id => l_trolin_tbl(1).line_id);

  150. l_mold_tbl := INV_MO_LINE_DETAIL_UTIL.query_rows(p_line_id => l_trolin_tbl(1).line_id);

  151. INV_PICK_WAVE_PICK_CONFIRM_PUB.Pick_Confirm(p_api_version_number => l_api_version,

  152. p_init_msg_list => l_init_msg_list,

  153. p_commit => l_commit,

  154. x_return_status => x_return_status,

  155. x_msg_count => x_msg_count,

  156. x_msg_data => x_msg_data,

  157. p_move_order_type => l_move_order_type,

  158. p_transaction_mode => 1,

  159. p_trolin_tbl => l_trolin_tbl,

  160. p_mold_tbl => l_mold_tbl,

  161. x_mmtt_tbl => x_mold_tbl,

  162. x_trolin_tbl => x_trolin_tbl);

  163. IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN

  164. DBMS_OUTPUT.PUT_LINE('E');

  165. FOR i IN 1..x_msg_count LOOP

  166. fnd_msg_pub.get(p_msg_index => i

  167. ,p_encoded => 'F'

  168. ,p_data => x_msg_data

  169. ,p_msg_index_out => l_msg_return);

  170. DBMS_OUTPUT.PUT_LINE(x_msg_data);

  171. END LOOP;

  172. RETURN;

  173. ELSE

  174. DBMS_OUTPUT.PUT_LINE('S');

  175. END IF;

  176. -- END LOOP;

  177. EXCEPTION

  178. WHEN OTHERS THEN

  179. DBMS_OUTPUT.PUT_LINE(SQLCODE ||':'||SQLERRM);

  180. END;

其他需求情况

有可能业务上只需要在发运出库的时候在交货号显示序列号和批次号,但是实际库存控制并没有这个需求,也可以在挑库确认后,通过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怎么实现批次序列号的销售出库这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0