Oracle EBS 采购 接收入库 接口开发

http://blog.itpub.net/25164132/viewspace-746657/

接收入库是项目中会经常碰到的开发,这类开发一般来说比较简单,但是接收入库在Oracle中其实涉及到很多模块,其中层次较多,也可以做得比较复杂。本文将尽可能深入细致地讨论接收入库的流程,种类,数据来源,数据的流动路径,以及各个数据点之间的对应关系。最后将给出一个较为全面的接收入库的样例代码。

接收入库的种类接收入库可以按照数据来源分为2种:
1. 
       对于po订单以及发放的接收入库;
2. 
       对于内部请购单生成的sales
order(后面的部分简称so)的接收入库;

接收入库还可以按照入库方式分为3种:
1.  直接入库:接收后自动入库;
2.  标准入库:先接收,后入库,分两个步骤;
3.  需要检验的接收入库:先接收,然后检验,最后入库;

对于这些不同类型的入库,程序的差别可能会很大。所以一个完整灵活可以应付所有接收入库的程序也是较为复杂的。

数据流动       
 我们将分析接收入库的数据来源,针对不同的接收入库类别,给出最常见实用的取数逻辑。最后我们将给出一个总体的数据流图,其中包含了各个数据点间的层次关系,帮助大家理解。
其中涉及到的较为重要的表(我们忽略了一些显而易见的表,比如po_headers_all,po_line_locations_all等等):

















mtl_supply 最重要的一张表,其中包括了所有可以接收入库的记录
Rcv_transaction 这张表的内容是已经接收入库的事物处理记录,在标准入库或检验入库的时候,我们可能需要其中的接收信息。
Rcv_shipment_headers 发运头表
Rcv_shipment_lines 发运行表
   

标准订单以及一揽子采购协议发放1.  对于标准订单,当订单被approve之后,系统会在mtl_supply这张表中插入该订单相关的记录,系统默认为每一个订单分配行生成一条mtl_supply数据,其supply_type_code值为“PO”,表示物料供应的来源,目前是来自po订单。所以mtl_supply表中,对于标准订单以及一揽子发放,其数据层次是明细到分配行的,即根据distribution_id可以唯一确定一个mtl_supply行:

SELECT pha.segment1,

pla.line_num,

plla.shipment_num,

pda.distribution_num,

ms.supply_type_code,

ms.quantity

FROM   mtl_supply    
       ms,

po_headers_all        pha,

po_lines_all          pla,

po_line_locations_all plla,

po_distributions_all  pda

WHERE  ms.po_distribution_id =
pda.po_distribution_id

AND 
  ms.supply_type_code = ‘PO‘

AND 
  pha.po_header_id = pla.po_header_id

AND 
  plla.po_header_id = pha.po_header_id

AND 
  plla.po_line_id = pla.po_line_id

AND 
  pda.line_location_id = plla.line_location_id

AND 
  pha.segment1 = ‘1000100‘

以上sql语句将筛选出订单编号为‘1000100’的订单可以接收的distribution行以及可以接收的数量。

注意:在这个时候,rcv_shipmet_headers以及rcv_shipment_lines这两张表中还没有数据,这是po订单与内部请购单接收数据流中的一个较大的差异。
造成这种差异的原因是:
对于po订单,其发运对象是外部供应商,系统无法控制以及检测外部供应商的发运动作,所以只能在做接收的时候,才能生成发运信息,在任何接收之前,系统是不知道任何发运数据的;
而对于内部请购单生成的Sales
Order来说,发运对象是公司内部其它组织或ou,发运信息是在其他组织或OU做SO的发运时就产生了,而不必等到接收的时候才产生相应的发运信息。

由于以上差异,在po订单做接收时,接口中不必提供shipment信息,而在po入库以及内部请购单生成的so接收的时候,则需要提供shipment信息。

2.  接下来,当我们为po订单做接收的时候,系统会生成相应的shipment信息,经过测试,每次接收会生成一个新的shipment头,每个接收行会生成一个新的shipment行。所以,对于po接收,其接收的transaction id与发运行的shipment line id是一一对应的,在做po入库的时候,可以利用这一点,通过shipment
line 找到可以入库的parent
transaction id。另外,对于po接收,其在发运行中的quantity
received与quantity
shipped字段的值总是一样的,因为发运记录是完全参照接收记录生成的。
3.  对于直接入库的订单,接收后将同时在RCV_TRANSACTION中生成接收记录以及入库记录;

对于标准接收则分为接收和入库两个步骤,接收生成接收事务处理记录,并且同时在MTL_SUPPLY中可以找到mtl_supply_type为“RECEIVING”的记录,表示存在可入库记录了,入库来源是“RECEIVING”。入库后再同一张表(RCV_TRANSACTION)中生成入库事务处理记录;虽然接收后在MTL_SUPPLY表中可以查到可入库的信息,但是因为接收后已经在RCV_TRANSACTION中产生了接收事务处理记录,理论上来说,以上两者的数据应当是等价的,但是这时候我们习惯于从RCV_TRANSACTION表中查找可以入库的记录。

对于需要检验的接收入库,在接收后,需要完成检验,对接收记录打上检验通过标记后,才能进行入库动作,最终生成入库事务处理记录。

标准订单接收入库数据流向图

对内部请购单生成的Sales
Order的接收入库
内部请购单因为涉及到内部销售订单以及发运信息,所以比PO单的接收多了若干环节,显得较为复杂。基本的数据流如下:
1.  创建内部请购单,审批成功后,通过请求生成对应的Sales Order,完成从PO表到OE表的第一个步骤的数据流动。可以通过OE表的Reference字段来追溯对应的请购单(IR)。这时候虽然在MTL_SUPPLY中也产生了供应数据,但是这个时候是无法对这个IR进行接收的,因为对应的SO还没有发运记录,没有发运怎么能接收呢。
2.  对SO进行挑库发放,确认发运后,在 RCV_SHIPMENT中生成了发运记录。完成了第二个步骤的数据流动。注意,由于存在SO拆行,以及分批发运的状况,所以发运行与IR的行是不存在严格意义上的数量对应关系的,一个IR行生成的SO行,可能被拆分在若干个发运记录中,这也是在做IR接收入库时,接口表要求插入发运信息的原因,对于IR的接收,是以发运事务处理为单位的。发放确认后,在MTL_SUPPLY中,将可以找到supply_type_code为“SHIPMENT”的供应记录,表示从这个时刻起,这个IR相关的订单可以开始接收了,接收来源是“SHIPMENT”;
3.  接下来的步骤基本和PO接收入库一致。值得注意的是在对IR生成的SO做接收时,可以发现一个明显的特点,接收事务处理界面中的可接收记录根据发运方式被拆成了多行,而不像PO接收时那样一个PO行对应一行可接收记录。这也直接说明了对于IR来说接收是以发运为单位进行的。

 

接口表注意事项不同的入库方式Oracle提供了三种可选的入库方式(在PO订单分配行界面维护):
1.  直接入库:接收后自动入库;
2.  标准入库:接收后,进行入库动作,才完成最终入库;
3.  要求检验的入库:接收后,进行检验,打印检验通过标记后,才能进行入库动作。

对于这三种接收入库,接口表通过不同的控制字段来完成期望的接收入库动作:

a)      
对于直接入库的接收,插接收事务处理的接口行表(rcv_transactions_interface)时的几个关键的状态字段:

rcv_transactions_interface.transaction_type    
    := ‘RECEIVE‘;

rcv_transactions_interface.auto_transact_code 
    := ‘DELIVER‘;

rcv_transactions_interface.destination_type_code 
  := ‘INVENTORY‘;

b)      
对于标准以及需检验的入库的接收,插接收事务处理的接口行表(rcv_transactions_interface)时的几个关键的状态字段:

rcv_transactions_interface.transaction_type    
    := ‘RECEIVE‘;

rcv_transactions_interface.auto_transact_code 
    := NULL;

rcv_transactions_interface.destination_type_code 
  := ‘ RECEIVING ‘;

c)      
对于接收甚至检验后的数据做入库时,插接收事务处理的接口行表(rcv_transactions_interface)时的几个关键的状态字段:

rcv_transactions_interface.transaction_type 
       := ‘DELIVER‘;

rcv_transactions_interface.auto_transact_code 
    := NULL;

rcv_transactions_interface.destination_type_code 
  := ‘INVENTORY‘;

可入库数量我们需要判断可入库数量,这是对入库接口数据的一项基本校验,是否有足够的数量可以入库,我们分别给出PO以及IR的可入库数量的算法:

对于PO单(标准采购订单,一揽子发放):

FUNCTION
check_po_valid_quantity(p_routing_id       IN
NUMBER

,p_line_location_id IN
NUMBER

,p_deliver_qty    
 IN NUMBER

,p_uom_code    
    IN VARCHAR2

,p_item_id    
     IN NUMBER) RETURN VARCHAR2 IS

l_qty 
          NUMBER := 0;

l_valid_quantity NUMBER := 0;

l_ship_uom_code  VARCHAR2(3);

CURSOR
cur_valid_lines(i_routing_id IN NUMBER) IS

SELECT ms.quantity, muom.uom_code

FROM   mtl_supply ms, rcv_transactions rt, mtl_units_of_measure
muom

WHERE  rt.transaction_id = ms.rcv_transaction_id

AND    rt.inspection_status_code =

decode(i_routing_id, 1,
rt.inspection_status_code, 2, ‘ACCEPTED‘)

AND    ms.supply_type_code = ‘RECEIVING‘

AND    ms.po_line_location_id = p_line_location_id

AND    muom.unit_of_measure = ms.unit_of_measure;

BEGIN

IF
(p_routing_id = ‘1‘ OR p_routing_id = ‘2‘) THEN

--standard or inspect required deliver

FOR rec_valid_line IN cur_valid_lines(p_routing_id) LOOP

l_qty := rec_valid_line.quantity;

--transact quantity according to uom

IF (rec_valid_line.uom_code <> p_uom_code)
THEN

l_qty := inv_convert.inv_um_convert(p_item_id,

6,

l_qty,

rec_valid_line.uom_code,

p_uom_code,

NULL,

NULL);

END IF;

l_valid_quantity := l_valid_quantity + l_qty;

END LOOP;

ELSIF
(p_routing_id = ‘3‘) THEN

-- direct deliver   

SELECT plla.quantity - plla.quantity_received - plla.quantity_cancelled,
muom.uom_code

INTO   l_valid_quantity, l_ship_uom_code

FROM   po_line_locations_all plla, mtl_units_of_measure
muom

WHERE  plla.quantity - plla.quantity_received -
plla.quantity_cancelled > 0

AND    muom.unit_of_measure =
plla.unit_meas_lookup_code

AND    plla.line_location_id = p_line_location_id;

--transact quantity according to uom

IF (l_ship_uom_code <> p_uom_code) THEN

l_valid_quantity :=
inv_convert.inv_um_convert(p_item_id,

6,

l_valid_quantity,

l_ship_uom_code,

p_uom_code,

NULL,

NULL);

END IF;

END
IF;

xxdomi_cn_conc_utl.debug(‘l_valid_quantity : ‘ || l_valid_quantity || ‘
;p_deliver_qty : ‘ ||

p_deliver_qty);

IF
(l_valid_quantity >= p_deliver_qty) THEN

RETURN ‘VALID‘;

ELSE

RETURN ‘INVALID‘;

END
IF;

EXCEPTION

WHEN OTHERS
THEN

xxdomi_cn_conc_utl.log_msg(‘check_po_valid_quantity: ‘ ||
SQLERRM);

RETURN ‘INVALID‘;

END
check_po_valid_quantity;

对于IR 
 
FUNCTION
check_ir_valid_quantity(p_routing_id  IN NUMBER
 
                 
              ,p_req_line_id IN
NUMBER
    
                 
           ,p_deliver_qty IN
NUMBER
    
                 
           ,p_uom_code    IN
VARCHAR2
    
                 
           ,p_item_id 
   IN NUMBER) RETURN VARCHAR2 IS
 
  l_qty            NUMBER :=
0;
    l_valid_quantity
NUMBER := 0;
  
 
  --valid lines for routing_id 1&2
 
  CURSOR cur_valid_lines(i_routing_id IN NUMBER) IS
 
    SELECT ms.quantity, muom.uom_code
 
    FROM   mtl_supply ms, rcv_transactions rt,
mtl_units_of_measure muom
 
    WHERE  ms.req_line_id =
p_req_line_id
    
 AND    ms.supply_type_code = ‘RECEIVING‘
 
    AND    ms.rcv_transaction_id =
rt.transaction_id
 
    AND    rt.inspection_status_code =
          
  decode(i_routing_id, 1, rt.inspection_status_code, 2,
‘ACCEPTED‘)
    
 AND    muom.unit_of_measure =
ms.unit_of_measure;
  
 
  --valid lines for routing_id 3
 
  CURSOR cur_dir_valid_lines IS
 
    SELECT ms.quantity, muom.uom_code
 
    FROM   mtl_supply ms, mtl_units_of_measure
muom
    
 WHERE  ms.req_line_id = p_req_line_id
 
    AND    ms.supply_type_code =
‘SHIPMENT‘
    
 AND    muom.unit_of_measure =
ms.unit_of_measure;
  
  BEGIN
    IF (p_routing_id = ‘1‘ OR
p_routing_id = ‘2‘) THEN    
 
    --standard or inspect required deliver
 
    FOR rec_valid_line IN cur_valid_lines(p_routing_id)
LOOP
    
   l_qty := rec_valid_line.quantity;
 
      --transact quantity according to
uom
    
   IF (rec_valid_line.uom_code <> p_uom_code)
THEN
    
     l_qty :=
inv_convert.inv_um_convert(p_item_id,
 
                 
                 
        6,
 
                 
                 
        l_qty,
 
                 
                 
        rec_valid_line.uom_code,
 
                 
                 
        p_uom_code,
 
                 
                 
        NULL,
 
                 
                 
        NULL);
 
      END IF;
 
      l_valid_quantity := l_valid_quantity +
l_qty;
    
 END LOOP;
   
ELSIF (p_routing_id = ‘3‘) THEN
      --direct
deliver 
    
 FOR rec_dir_valid_line IN cur_dir_valid_lines LOOP
 
      l_qty :=
rec_dir_valid_line.quantity;
        --transact
quantity according to uom
 
      IF (rec_dir_valid_line.uom_code <>
p_uom_code) THEN
 
        l_qty :=
inv_convert.inv_um_convert(p_item_id,
 
                 
                 
        6,
 
                 
                 
        l_qty,
 
                 
                 
        rec_dir_valid_line.uom_code,
          
                 
                
p_uom_code,
    
                 
                 
     NULL,
 
                 
                 
        NULL);
 
      END IF;
 
      l_valid_quantity := l_valid_quantity +
l_qty;
    
 END LOOP;
    END
IF;
  
    IF (l_valid_quantity >=
p_deliver_qty) THEN
 
    RETURN ‘VALID‘;
    ELSE
 
    RETURN ‘INVALID‘;
 
  END IF;
  EXCEPTION
 
  WHEN OTHERS THEN
 
    xxdomi_cn_conc_utl.log_msg(‘check_ir_valid_quantity: ‘ ||
SQLERRM);
    
 RETURN ‘INVALID‘;
  END
check_ir_valid_quantity;

以上检查程序综合考虑了不同的三种入库方式,其中p_routing_id有三种值:
1:表示标准入库;
2:表示需要检验的入库;
3:表示直接入库;
 
              
  
以上程序也考虑到了单位的转换,支持入库单位与接收单位不想同的情况下的入库数量校验。
对于带批次或序列号的接收入库       
 对于带批次或序列号的接收入库,对于1行rcv_transactions_interface记录需要额外插两张MTL的接口表。这里有一个比较诡异的地方,就是接收入库时,插rcv_serials_interface,以及rcv_lots_interface这两张表是没用的,而一定要插 mtl_transaction_lots_interface以及mtl_serial_numbers_interface这两张MTL表,而且对应的要设置
rcv_transactions_interface.use_mtl_lot
:= 2;
rcv_transactions_interface.use_mtl_serial
:= 2;
以下程序在11i下验证通过。

--lot
info------------

IF (rec_line.lot_number IS NOT NULL) THEN

mtl_transaction_lots_interfac.last_update_date 
     := SYSDATE;

mtl_transaction_lots_interfac.last_updated_by 
      := fnd_global.user_id;

mtl_transaction_lots_interfac.creation_date 
        := SYSDATE;

mtl_transaction_lots_interfac.created_by    
        := fnd_global.user_id;

mtl_transaction_lots_interfac.last_update_login 
    := -1;

mtl_transaction_lots_interfac.product_code 
         := ‘RCV‘;

mtl_transaction_lots_interfac.product_transaction_id :=
rcv_transactions_interface.interface_transaction_id;

mtl_transaction_lots_interfac.lot_number    
        := rec_line.lot_number;

mtl_transaction_lots_interfac.transaction_quantity 
 := l_iface_rcv_rec.quantity;

mtl_transaction_lots_interfac.primary_quantity 
     := l_primary_qty;

SELECT mtl_material_transactions_s.NEXTVAL

INTO 
 mtl_transaction_lots_interfac.transaction_interface_id

FROM   dual;

l_primary_qty :=1;

INSERT INTO mtl_transaction_lots_interface VALUES mtl_transaction_lots_interfac;

END IF;

--serial
info

IF (serial_number IS NOT NULL) THEN

mtl_serial_numbers_interface.last_update_date 
     := SYSDATE;

mtl_serial_numbers_interface.last_updated_by 
      := fnd_global.user_id;

mtl_serial_numbers_interface.creation_date 
        := SYSDATE;

mtl_serial_numbers_interface.created_by    
        := fnd_global.user_id;

mtl_serial_numbers_interface.last_update_login 
    := -1;

mtl_serial_numbers_interface.product_code    
      := ‘RCV‘;

mtl_serial_numbers_interface.fm_serial_number 
     :=serial_number;

mtl_serial_numbers_interface.to_serial_number 
     :=serial_number;

mtl_serial_numbers_interface.process_flag    
      := 1;

mtl_serial_numbers_interface.product_transaction_id :=
l_iface_rcv_rec.interface_transaction_id;

SELECT mtl_material_transactions_s.NEXTVAL

INTO 
 mtl_serial_numbers_interface.transaction_interface_id

FROM   dual;

INSERT INTO mtl_serial_numbers_interface VALUES mtl_serial_numbers_interface;

END IF;

Oracle EBS 采购 接收入库 接口开发,码迷,mamicode.com

时间: 2024-12-22 08:53:25

Oracle EBS 采购 接收入库 接口开发的相关文章

ORACLE EBS xml publisher 报表输出字符字段前部&quot;0&quot;被EXCEL自动去掉问题

http://www.cnblogs.com/lzsu1989/archive/2012/10/17/2728528.html Oracle  EBS 提供多种报表的开发和输出形式,由于MS Excel在处理数据方面的优势明显,报表输出用Excel打开是很常见的开发项. 但是正是由于Excel的“过于智能而不智能”,导致有时输出字段会被Excel自动处理,导致数据错误. 例如: 系统内部字段,物料编码/订单标号 等等字段在数据库内存储的格式为 varchar, 在某些业务或者需求下,编码方式为全

Oracle EBS Form个性化开发

Form个性化开发内容不是很多,在国内的项目上客户化界面上基本用不上,相关开发文档有的讲解的很详细,有的讲解太过简练,希望通过这个文档可以给我们这些刚开始做个性化的新手快速完成需求,不要再这方面花费过多的时间,我们都做过Form开发,可以把Form个性化的开发都用类比Form开发去理解就很快能上手. Form启动时,所有与当前Function相关的个性化规则都会被加载到内存,当Form触发特定的Event时候,系统会搜索相应的个性化规则并进行匹配,得到匹配的规则,再按照规则序号从小到大一次执行对

EBS采购模块中的快速接收和快速接收事务

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 快速功能是一个快速输入收货和接收事务的方法. 在收货窗口上,如果你在查找期望收货窗口上指定了或者隐式指定了来源类型(你如果你输入了,比如,采购订单编号,就隐式指定了来源类型),那么就可以使用快速功能.在接收事务窗口,不论查找接收事务窗口上的搜索条件,快速功能都是可用的.在行上的任意手工操作都会禁用快速按钮,且直到你再次点击查找按钮才会启用快速按钮. 当你在收货窗口中选择快速按钮时,采购模块会

Oracle EBS供应商接口导入(转)

原文地址 Oracle EBS供应商接口导入 1.供应商导入组成供应商导入主要分为供应商头信息导入.供应商地点信息导入.供应商联系人导入三个部分的信息,其他按实际需求进行添加.供应商头信息导入:导入供应商的头信息供应商地点信息导入:导入供应商的地点.地址信息供应商联系人信息导入:导入对应地址上的联系人信息供应商地点附加信息导入:导入供应商对应地点上的附加信息供应商税率导入:导入供应商地点上的税信息及税率供应商付款方法导入:导入供应商地点上的默认付款方法供应商银行导入:导入供应商地点上对应的银行.

C#/ASP.NET MVC微信公众号接口开发之从零开发(二) 接收微信消息并且解析XML(附源码)

文章导读: C#微信公众号接口开发之从零开发(一) 接入微信公众平台 微信接入之后,微信通过我们接入的地址进行通信,其中的原理是微信用户发送消息给微信公众账号,微信服务器将消息以xml的形式发送到我们的绑定的地址上,通过解析XML数据,获取到微信用户发送的消息,让根据微信消息(文本:关键字,图片,语音等等)回复XML格式的数据给微信服务器,微信服务器再将接收到的消息返回给用户微信. 我们所需要做的:接收消息和返回消息 一.创建实体类 首先看文档http://mp.weixin.qq.com/wi

供应商导入的API补充(详解EBS接口开发之供应商导入)(转)

原文地址  供应商导入的API补充(详解EBS接口开发之供应商导入) --供应商 --创建 AP_VENDOR_PUB_PKG.Create_Vendor ( p_api_version IN NUMBER, p_init_msg_list IN VARCHAR2 := FND_API.G_FALSE, p_commit IN VARCHAR2 := FND_API.G_FALSE, p_validation_level IN NUMBER := FND_API.G_VALID_LEVEL_FU

EBS采购模块中的级联接收和级联接收事务

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 级联接收和级联接收事务 级联功能对来自于同一个供应商和同一个物料的给定数量,且跨越多个发运和分配时,帮助进行分配.在收货窗口,如果你在查找预期收货窗口指定了一个供应商和物料并且收货组织选项窗口中允许级联接收的话,这个功能是可用的.在收货事务窗口,如果你在查找收货事务窗口指定了物料的话,那个级联功能对交货是可用的.在任何一行上做了任何手工操作都会禁用级联按钮,并且它不会被启用直到又在合适的查找

Oracle EBS 如何月结[Z]

概述应付模块的多数业务基于采购和库存的操作,因此应付模块的月结应该在采购模块和库存模块月结后才能关闭会计期.月结步骤在每个会计期末,应付模块的月结应遵循以下流程:1.检查业务是否全部录入;2.检查是否有未验证.暂挂发票;3.更新到期的远期付款状态;4.检查应付业务是否生成分录;5.应付业务传送到总帐;6.确认应付分录全部传送总帐;7.创建成批增加;8.复核凭证,确认无误后过帐;9.确认及核对供应商余额;10.关闭应付会计期间;11.打开新的会计期;12.为通过手工方式进入存货成本的调整准备数据:

Oracle EBS 如何月结、对账[Z]

在Oracle系统处理月结业务时,需要遵循一定的操作顺序.这些业务,牵涉到相应的模块,包括:应付模块.采购模块.库存模块.应收模块.薪资模块.固定资产和总帐模块等 在Oracle系统中,总帐模块处于财务核算的核心地位,它从其他模块中接收财务信息.总帐接收到的财务信息与子模块业务必须保持一致,才能保证整个系统的帐务是正确的,所以要进行对帐. 后面将描述一下模块之间的关帐顺序及模块间关帐要完成的步骤 一.Oracle EBS 月结应付(AP)对账顺序 步骤,1.检查业务是否全部录入:2.检查是否有