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

来源:这里教程网 时间:2026-03-03 13:14:45 作者:

转:http://blog.csdn.net/shishun123/article/details/5836525

      随着制造企业对生产销售的控制越来越高,越来越多的制造型企业增加了对物料的批次、序列号的控制。我们可以在库存职责中的:物料 –> 主组织物料/组织产品 -> 库存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.                
  11.   -- API specific declarations     
  12.   l_header_id              NUMBER :=  ;     
  13.   l_trohdr_rec             INV_MOVE_ORDER_PUB.TROHDR_REC_TYPE;     
  14.   l_trohdr_val_rec         INV_MOVE_ORDER_PUB.TROHDR_VAL_REC_TYPE;     
  15.   l_trolin_tbl             INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;     
  16.   o_trolin_tbl             INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;     
  17.   l_trolin_val_tbl         INV_MOVE_ORDER_PUB.TROLIN_VAL_TBL_TYPE;     
  18.   x_trolin_tbl             INV_MOVE_ORDER_PUB.TROLIN_TBL_TYPE;     
  19.   x_trolin_val_tbl         INV_MOVE_ORDER_PUB.TROLIN_VAL_TBL_TYPE;     
  20.   x_trohdr_rec             INV_MOVE_ORDER_PUB.TROHDR_REC_TYPE;     
  21.   x_trohdr_val_rec         INV_MOVE_ORDER_PUB.TROHDR_VAL_REC_TYPE;     
  22.              
  23.   -- Cursor to load Move Order Headers     
  24.   l_mold_tbl             INV_MO_LINE_DETAIL_UTIL.g_mmtt_tbl_type;     
  25.   x_mold_tbl             INV_MO_LINE_DETAIL_UTIL.g_mmtt_tbl_type;     
  26.   l_move_order_type      NUMBER :=  3 ;     
  27.   l_msg_return           NUMBER;     
  28.        
  29.   x_number_of_rows          NUMBER   ;     
  30.   x_detailed_qty            NUMBER   ;     
  31.   x_revision                VARCHAR2( 20 ) ;     
  32.   x_locator_id              NUMBER   ;     
  33.   x_transfer_to_location    NUMBER   ;     
  34.   x_lot_number              VARCHAR2( 80 ) ;     
  35.   x_expiration_date         DATE     ;     
  36.   x_transaction_temp_id     NUMBER   ;     
  37.   p_transaction_header_id   NUMBER   ;     
  38.   p_transaction_mode        NUMBER   ;     
  39.   p_move_order_type         NUMBER :=  3 ;     
  40.   p_serial_flag             VARCHAR2( 1 ) ;     
  41.   p_plan_tasks              BOOLEAN  ;     
  42.   p_auto_pick_confirm       BOOLEAN  ;     
  43.   p_commit                  BOOLEAN  ;     
  44.   l_t_header_id             NUMBER;     
  45.   l_lot_number              VARCHAR2( 80 )   :=  'SLT0021' ;    --mtl_lot_numbers.lot_number;     
  46.   l_serial_number           VARCHAR2( 20 )   :=  '3.06.S0019' ; --mtl_serial_numbers.serial_number     
  47.   l_subinvetory_code        VARCHAR2( 10 )   :=  'BJJF_CLK' ;   --mtl_secondary_inventories.secondary_inventory_name     
  48.   l_locator_id              NUMBER         :=  42 ;           --mtl_item_locations.inventory_location_id     
  49.   l_trx_header_id           NUMBER         :=  93023 ;        --mtl_txn_request_headers.header_id     
  50. BEGIN     
  51.       
  52.          
  53.     FND_GLOBAL.APPS_INITIALIZE( 1371 50627 660 );  -- Suhasini / Mfg  Mgr / INV     
  54.           
  55.   INV_MOVE_ORDER_PUB.Get_Move_Order(      
  56.       P_API_VERSION_NUMBER  => l_api_version         
  57.      , P_INIT_MSG_LIST       => l_init_msg_list       
  58.      , P_RETURN_VALUES       => l_return_values       
  59.      , X_RETURN_STATUS       => x_return_status              
  60.      , X_MSG_COUNT           => x_msg_count       
  61.      , X_MSG_DATA                => x_msg_data           
  62.      , P_HEADER_ID           => l_trx_header_id-- 93023      
  63.      , P_HEADER                => NULL     
  64.      , X_TROHDR_REC       => l_trohdr_rec           
  65.      , X_TROHDR_VAL_REC      => l_trohdr_val_rec       
  66.      , X_TROLIN_TBL          => l_trolin_tbl           
  67.      , X_TROLIN_VAL_TBL      => l_trolin_val_tbl      
  68.   );      
  69.         
  70.       
  71.       
  72.       
  73.       
  74.    -- Print the Move Order Header/Lines to be processed     
  75.    IF (x_return_status = FND_API.G_RET_STS_SUCCESS) THEN     
  76.                                      
  77.                        
  78.          l_trohdr_rec.operation   :=   INV_GLOBALS.G_OPR_UPDATE;        
  79.                         
  80.        --  FOR i IN  1 ..l_trolin_tbl.COUNT LOOP     
  81.                       
  82.               l_trolin_tbl( 1 ).from_subinventory_code := l_subinvetory_code;     
  83.               l_trolin_tbl( 1 ).from_locator_id        := l_locator_id;     
  84.               l_trolin_tb1(i).lot_number             := l_lot_number;     
  85.               l_trolin_tbl( 1 ).serial_number_start    := l_serial_number;     
  86.               l_trolin_tbl( 1 ).serial_number_end      := l_serial_number;     
  87.               l_trolin_tbl( 1 ).attribute1             :=  'update move order test!' ;     
  88.               l_trolin_tbl( 1 ).operation              := INV_GLOBALS.G_OPR_UPDATE;     
  89.        --  END LOOP;     
  90.    ELSE     
  91.      DBMS_OUTPUT.PUT_LINE( 'Get_Move_Order error!' );     
  92.      RETURN;     
  93.    END IF;     
  94.                  
  95.         
  96.    INV_MOVE_ORDER_PUB.Process_Move_Order_Line( p_api_version_number =>  1.0      
  97.                                               ,p_init_msg_list  => l_init_msg_list     
  98.                                               ,p_return_values  => l_return_values     
  99.                                               ,p_commit         => l_commit     
  100.                                               ,x_return_status  => x_return_status     
  101.                                               ,x_msg_count      => x_msg_count     
  102.                                               ,x_msg_data       => x_msg_data     
  103.                                               ,p_trolin_tbl     => l_trolin_tbl     
  104.                                               ,p_trolin_old_tbl => l_trolin_tbl     
  105.                                               ,x_trolin_tbl     => x_trolin_tbl);     
  106.            
  107.    IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN     
  108.           
  109.      FOR i IN  1 ..x_msg_count LOOP     
  110.        fnd_msg_pub.get(p_msg_index     => i     
  111.                       ,p_encoded       =>  'F'      
  112.                       ,p_data          => x_msg_data     
  113.                       ,p_msg_index_out => l_msg_return);     
  114.        DBMS_OUTPUT.PUT_LINE(x_msg_data);     
  115.      END LOOP;       
  116.            
  117.      RETURN;     
  118.    ELSE     
  119.       DBMS_OUTPUT.PUT_LINE( 'MODIFY SUCESS!' );     
  120.    END IF;     
  121.         
  122.       
  123. /*  inv_mo_line_detail_util.reduce_allocation_quantity(    
  124.       x_return_status => x_return_status    
  125.      ,p_transaction_temp_id => 2242994    
  126.      ,p_quantity => 1    
  127.      ,p_secondary_quantity => 1) ;    
  128.      
  129.     IF x_return_status <> 'S' THEN    
  130.       DBMS_OUTPUT.PUT_LINE('EE');    
  131.     ELSE    
  132.       DBMS_OUTPUT.PUT_LINE('SS');    
  133.     END IF;*/      
  134.       
  135.  inv_replenish_detail_pub.line_details_pub(                    
  136.     p_line_id               =>   l_trolin_tbl( 1 ).line_id     
  137.   , x_number_of_rows        =>   x_number_of_rows             
  138.   , x_detailed_qty          =>   x_detailed_qty               
  139.   , x_return_status         =>   x_return_status              
  140.   , x_msg_count             =>   x_msg_count                  
  141.   , x_msg_data              =>   x_msg_data                   
  142.   , x_revision              =>   x_revision                   
  143.   , x_locator_id            =>   x_locator_id                 
  144.   , x_transfer_to_location  =>   x_transfer_to_location       
  145.   , x_lot_number            =>   x_lot_number                 
  146.   , x_expiration_date       =>   x_expiration_date            
  147.   , x_transaction_temp_id   =>   x_transaction_temp_id        
  148.   , p_transaction_header_id =>   NULL      
  149.   , p_transaction_mode      =>   NULL           
  150.   , p_move_order_type       =>   p_move_order_type            
  151.   , p_serial_flag           =>   FND_API.G_FALSE                         
  152.   , p_plan_tasks            =>   FALSE                        
  153.   , p_auto_pick_confirm     =>   FALSE                       
  154.   , p_commit                =>   FALSE);             
  155.       
  156.    IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN     
  157.      DBMS_OUTPUT.PUT_LINE( 'E' );     
  158.     FOR i IN  1 ..x_msg_count LOOP     
  159.       fnd_msg_pub.get(p_msg_index     => i     
  160.                     ,p_encoded       =>  'F'      
  161.                     ,p_data          => x_msg_data     
  162.                     ,p_msg_index_out => l_msg_return);     
  163.       DBMS_OUTPUT.PUT_LINE(x_msg_data);     
  164.      END LOOP;       
  165.                      
  166.     RETURN;     
  167.   ELSE     
  168.     DBMS_OUTPUT.PUT_LINE( 'ssssss' );     
  169.     DBMS_OUTPUT.PUT_LINE( 'x_number_of_rows:        '  || to_char(x_number_of_rows));     
  170.     DBMS_OUTPUT.PUT_LINE( 'x_locator_id:            '  || to_char(x_locator_id));     
  171.     DBMS_OUTPUT.PUT_LINE( 'x_lot_number:            '  || to_char(x_lot_number));     
  172.     DBMS_OUTPUT.PUT_LINE( 'x_transfer_to_location:  '  || to_char(x_transfer_to_location));     
  173.      DBMS_OUTPUT.PUT_LINE( 'x_transaction_temp_id:  '  || to_char(x_transaction_temp_id));     
  174.   END IF;      
  175.       
  176.       
  177.   l_trolin_tbl := INV_Trolin_Util.Query_Rows(p_line_id => l_trolin_tbl( 1 ).line_id);     
  178.   l_mold_tbl   := INV_MO_LINE_DETAIL_UTIL.query_rows(p_line_id => l_trolin_tbl( 1 ).line_id);     
  179.          
  180.        
  181.   INV_PICK_WAVE_PICK_CONFIRM_PUB.Pick_Confirm(p_api_version_number  => l_api_version,     
  182.                                               p_init_msg_list       => l_init_msg_list,     
  183.                                               p_commit              => l_commit,     
  184.                                               x_return_status       => x_return_status,     
  185.                                               x_msg_count           => x_msg_count,     
  186.                                               x_msg_data             => x_msg_data,     
  187.                                               p_move_order_type     => l_move_order_type,     
  188.                                               p_transaction_mode    =>  1 ,     
  189.                                               p_trolin_tbl          => l_trolin_tbl,     
  190.                                               p_mold_tbl            => l_mold_tbl,     
  191.                                               x_mmtt_tbl            => x_mold_tbl,     
  192.                                               x_trolin_tbl          => x_trolin_tbl);     
  193.       
  194.   IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN     
  195.      DBMS_OUTPUT.PUT_LINE( 'E' );     
  196.     FOR i IN  1 ..x_msg_count LOOP     
  197.       fnd_msg_pub.get(p_msg_index     => i     
  198.                     ,p_encoded       =>  'F'      
  199.                     ,p_data          => x_msg_data     
  200.                     ,p_msg_index_out => l_msg_return);     
  201.       DBMS_OUTPUT.PUT_LINE(x_msg_data);     
  202.      END LOOP;       
  203.                      
  204.     RETURN;     
  205.   ELSE     
  206.     DBMS_OUTPUT.PUT_LINE( 'S' );     
  207.   END IF;     
  208.       
  209.   --   END LOOP;     
  210. EXCEPTION     
  211.   WHEN OTHERS THEN       
  212.     DBMS_OUTPUT.PUT_LINE(SQLCODE || ':' ||SQLERRM);     
  213.               
  214. 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 ;

相关推荐