一个Business Event+Workflow的例子(基于R12)

今天做了个Business events + Workflow 的例子,记录一下。

功能描述:

当表中新增一条INVOICE信息,自动触发Business events, 然后调用Workflow,发Notification 给审批者审批。

 

主要目的是测试Business events 的功能,学习一下。

 

测是测通了,但做完后,发觉并没有了解Business events的优势,因为这样的功能,完全可以在记录新增时直接调用Workflow来处理,感觉系统标准的Business events也无非是在某个操作完成后,触发一个Events,来完成后继的操作,就算有延迟处理(Defer)的功能,似乎我们也可通过database job 来实现,订阅(Subscriptions)功能也似乎可以写Package来实现不同的业务逻辑的分支处理。

 

如果有TX看到我的困惑,请不吝赐教!

 

下面是例子的详细步骤。

 

1.  建立客户化表c_apps.c_customer_invoices_all,当表中新增记录时,触发Business events

2.  Events 一旦触发,做两个动作:往客户化表c_apps.c_customer_invoice_events 中插入该events的相关信息,然后启动客制化的Workflow 发一个Notification给审批人。

3.审批人收到Notification, 进行审批并给出审批意见


开发过程:
1. 建表
2. 定义Events
3. 开发Workflow并上传注册
4. 定义Event subscription
5. 新增数据并查看结果
 

建表:

1.业务数据表,用来存测试发票

create table c_apps.c_customer_invoices_all

(invoice_id number,

 invoice_date date,

 invoice_amount number,

 submit_id number,

 submit_date date,

 approval_id number,

 approval_date date,

 approval_memo varchar2(100),

 approval_status varchar2(1))

 

 create sequence c_apps.c_customer_invoice_s

 

2. 业务事件表,用来存事件信息

 create table c_apps.c_customer_invoice_events

(event_id number,

 event_name varchar2(100),

 event_key varchar2(100),

 event_data varchar2(100),

 event_date date,

 invoice_id number,

 submit_id number)

 

 create sequence c_apps.c_customer_invoice_event_s

 

定义Business events

Path: System administrator/Administrator Workflow/Business Events

 

bb

注意: Event name 需要符合一定的规范,可参考系统内置的Event name来定义

          Owner Name/Tag 按实际的应用来输入application short name

 

定义Workflow

使用Workflow builder 开发一个新的Workflow item type

bb

注意:Attributes 中的INVOICE_ID/SUBMIT_ID将来自于EventParameter list. 不用进行初始化赋值,因为Raise event的时候会由程序提供

ENAME/EKEY/EMSG用来存放Event的相关信息

3Function 的功能如下:

GET_SUBMIT_INFO: 取得提交人的信息和审批人的信息并初始化各个Attributes

INVOICE_APPROVAL_ACTION: 审批分支的处理过程

INVOICE_REJECT_ACTION: 拒绝分支的处理过程

 

INVAPP_EVENTBusiness event activity.

 

Main Process如下:

bb

Event定义如下:

bb
注意: 这里的Event action 一定要是receive,这表示这个activity是用来接收event data的,而不是用来触发一个Event.

 

bb

bb

注意,上面三个即是把Event 的信息传给之前定义的3Attributes.

 

 

Lookup Types定义如下:

bb

 

Message 定义如下:

bbbbbb


 


 

Notification的定义如下:


 

bbbb

注意Performer的定义,即为接收人

 

上传Workflow并注册至系统

 

Event subscription 的定义
bb

 
bb

注意,Phase 定义在100以下的为即时处理

注意: PL/SQL Rule Function 里为客制化的程序,用来完成Event 信息的保存和Event的初始化

Workflow Type 里既为上面开发的Workflow, Process 为里面唯一的Main_process

 

编写Package, 代码如下:

注: 假定审批者与提交者为同一个人

 

 create or replace package body c_customer_invoice_pkg is


  --用来生成测试数据及调用Events

  procedure insert_data is

  

    l_invoice_id number;

  begin

  

    select c_apps.c_customer_invoice_s.nextval into l_invoice_id from dual;

    --Insert 数据
    --3137为我的user id,此为测试方便,直接用。

    insert into c_apps.c_customer_invoices_all

      (invoice_id,

       invoice_date,

       invoice_amount,

       submit_id,

       submit_date,

       approval_id,

       approval_date,

       approval_memo,

       approval_status)

    values

      (l_invoice_id, sysdate, 1000, 3137, sysdate, null, null, null, null);

    commit;

    --调用过程启动Event

    raise_event(l_invoice_id, 3137);

  end insert_data;

  

  --用来启动Event

  PROCEDURE raise_event(pi_invoice_id in NUMBER, pi_submit_id in NUMBER) is

  

    l_parameter_list wf_parameter_list_t := wf_parameter_list_t();

    l_parameter_t    wf_parameter_t := wf_parameter_t(null, null);

    l_event_key      NUMBER;

    l_event_data     varchar2(300);

  

    l_message varchar2(10);

  

  BEGIN

    

    --用invoice id 做为event key

    l_event_key := pi_invoice_id;

    

    --定义event的参数  

    l_parameter_t.setName('INVOICE_ID');

    l_parameter_t.setVALUE(pi_invoice_id);

    l_parameter_list.extend;

    l_parameter_list(1) := l_parameter_t;

  

    l_parameter_t.setName('SUBMIT_ID');

    l_parameter_t.setVALUE(pi_submit_id);

    l_parameter_list.extend;

    l_parameter_list(2) := l_parameter_t;

  

    --启动  

    wf_event.raise(p_event_name => 'oracle.apps.c_apps.invoice.approval',

                   p_event_key  => l_event_key,

                   --p_event_data => l_event_data,

                   p_parameters => l_parameter_list);

    commit;

  

    l_parameter_list.DELETE;   

     

  END raise_event;


  --此过程设置在Subscription的rule function中,用来往表中写入Event信息  

  FUNCTION rule_function(p_subscription in RAW,

                         p_event        in out NOCOPY WF_EVENT_T)

    return varchar2 is

  

    l_rule            VARCHAR2(20);

    l_parameter_list  wf_parameter_list_t := wf_parameter_list_t();

    l_parameter_t     wf_parameter_t := wf_parameter_t(null, null);

    i_parameter_name  l_parameter_t.name%type;

    i_parameter_value l_parameter_t.value%type;

    i                 pls_integer;

  

    l_invoice_id l_parameter_t.value%type;

    l_submit_id  l_parameter_t.value%type;

  BEGIN

  

    if p_event.geteventname() = 'oracle.apps.c_apps.invoice.approval' then

      --获取Event的参数

      l_parameter_list := p_event.getParameterList();

      if l_parameter_list is not null then

        i := l_parameter_list.FIRST;

        --获取参数的值

        while (i <= l_parameter_list.LAST) loop

          i_parameter_name  := null;

          i_parameter_value := null;

        

          i_parameter_name  := l_parameter_list(i).getName();

          i_parameter_value := l_parameter_list(i).getValue();

        

          if i_parameter_name is not null then

            if i_parameter_name = 'INVOICE_ID' then

              l_invoice_id := i_parameter_value;

            elsif i_parameter_name = 'SUBMIT_ID' then

              l_submit_id := i_parameter_value;

            end if;

          end if;

          i := l_parameter_list.NEXT(i);

        end loop;

      

      end if;

      --写入Event表

      insert into c_apps.c_customer_invoice_events

        (event_id,

         event_name,

         event_key,

         event_data,

         event_date,

         invoice_id,

         submit_id)

      values

        (c_apps.c_customer_invoice_event_s.nextval,

         p_event.getEventName,

         p_event.getEventKey,

         p_event.getEventData,

         sysdate,

         l_invoice_id,

         l_submit_id);

      

      --调用系统标准的Event rule

      l_rule := wf_rule.default_rule(p_subscription, p_event);

    

    end if;

    return('SUCCESS');

  EXCEPTION

    WHEN OTHERS THEN

      wf_core.context('c_customer_invoice_pkg',

                      'rule_function',

                      p_event.geteventname(),

                      p_subscription);

      wf_event.seterrorinfo(p_event, 'ERROR');

      RETURN 'ERROR';

  END rule_function;


  --用于Workflow,取得submit/approval的人员信息及发票信息

  PROCEDURE get_submit_info(itemtype  IN VARCHAR2,

                            itemkey   IN VARCHAR2,

                            actid     IN NUMBER,

                            funcmode  IN VARCHAR2,

                            resultout OUT NOCOPY VARCHAR2) is

    l_invoice_id     NUMBER;

    l_invoice_amount NUMBER;

    l_invoice_date   date;

  

    l_orig_system wf_roles.orig_system%TYPE := 'PER';

  

    l_submit_id           NUMBER;

    l_submit_name         wf_roles.NAME%TYPE;

    l_submit_display_name wf_roles.display_name%TYPE;

  

    l_approval_id           NUMBER;

    l_approval_name         wf_roles.NAME%TYPE;

    l_approval_display_name wf_roles.display_name%TYPE;

  begin

    IF (funcmode <> wf_engine.eng_run) THEN

    

      resultout := wf_engine.eng_null;

      RETURN;

    

    END IF;

  

    l_invoice_id := wf_engine.getitemattrnumber(itemtype => itemtype,

                                                itemkey  => itemkey,

                                                aname    => 'INVOICE_ID');

  

    l_submit_id := wf_engine.getitemattrnumber(itemtype => itemtype,

                                               itemkey  => itemkey,

                                               aname    => 'SUBMIT_ID');

  

    wf_directory.GetRoleName(p_orig_system    => l_orig_system,

                             p_orig_system_id => l_submit_id,

                             p_name           => l_submit_name,

                             p_display_name   => l_submit_display_name);

  

    wf_engine.setitemattrtext(itemtype => itemtype,

                              itemkey  => itemkey,

                              aname    => 'SUBMIT_NAME',

                              avalue   => l_submit_name);

  

    wf_engine.setitemattrtext(itemtype => itemtype,

                              itemkey  => itemkey,

                              aname    => 'SUBMIT_DSP_NAME',

                              avalue   => l_submit_display_name);

  

    wf_directory.GetRoleName(p_orig_system    => l_orig_system,

                             p_orig_system_id => l_submit_id,

                             p_name           => l_approval_name,

                             p_display_name   => l_approval_display_name);

  

    wf_engine.setitemattrnumber(itemtype => itemtype,

                                itemkey  => itemkey,

                                aname    => 'APPROVAL_ID',

                                avalue   => l_submit_id);

    wf_engine.setitemattrtext(itemtype => itemtype,

                              itemkey  => itemkey,

                              aname    => 'APPROVAL_NAME',

                              avalue   => l_approval_name);

  

    wf_engine.setitemattrtext(itemtype => itemtype,

                              itemkey  => itemkey,

                              aname    => 'APPROVAL_DSP_NAME',

                              avalue   => l_approval_display_name);

  

    select invoice_amount, invoice_date

      into l_invoice_amount, l_invoice_date

      from c_apps.c_customer_invoices_all

     where invoice_id = l_invoice_id;

  

    wf_engine.setitemattrnumber(itemtype => itemtype,

                                itemkey  => itemkey,

                                aname    => 'INVOICE_AMOUNT',

                                avalue   => l_invoice_amount);

  

    wf_engine.SetItemAttrDate(itemtype => itemtype,

                              itemkey  => itemkey,

                              aname    => 'INVOICE_DATE',

                              avalue   => l_invoice_date);

    resultout := 'COMPLETE';

  EXCEPTION

    when others then

      wf_core.context('C_CUSTOMER_INVOICE_PKG',

                      'get_submit_info',

                      itemtype,

                      itemkey,

                      TO_CHAR(actid),

                      funcmode,

                      SQLERRM);

      raise;

  end get_submit_info;

  

  --用于Workflow的审批分支

  PROCEDURE invoice_approval(itemtype  IN VARCHAR2,

                             itemkey   IN VARCHAR2,

                             actid     IN NUMBER,

                             funcmode  IN VARCHAR2,

                             resultout OUT NOCOPY VARCHAR2) is

  

    l_invoice_id    NUMBER;

    l_approval_memo c_apps.c_customer_invoices_all.approval_memo%TYPE;

    l_approval_id   NUMBER;

  

  begin

    IF (funcmode <> wf_engine.eng_run) THEN

    

      resultout := wf_engine.eng_null;

      RETURN;

    

    END IF;

    l_invoice_id := wf_engine.getitemattrnumber(itemtype => itemtype,

                                                itemkey  => itemkey,

                                                aname    => 'INVOICE_ID');

  

    l_approval_id := wf_engine.getitemattrnumber(itemtype => itemtype,

                                                 itemkey  => itemkey,

                                                 aname    => 'APPROVAL_ID');

  

    l_approval_memo := wf_engine.getitemattrtext(itemtype => itemtype,

                                                 itemkey  => itemkey,

                                                 aname    => 'APPROVAL_MEMO');

  

    UPDATE c_apps.c_customer_invoices_all

       SET approval_id     = l_approval_id,

           approval_date   = sysdate,

           approval_memo   = l_approval_memo,

           approval_status = 'Y'

     WHERE invoice_id = l_invoice_id;

    resultout := 'COMPLETE';

  EXCEPTION

    when others then

      wf_core.context('C_CUSTOMER_INVOICE_PKG',

                      'invoice_approval',

                      itemtype,

                      itemkey,

                      TO_CHAR(actid),

                      funcmode,

                      SQLERRM);

      raise;

  end invoice_approval;

  

  --用于Workflow的拒绝分支

  PROCEDURE invoice_reject(itemtype  IN VARCHAR2,

                           itemkey   IN VARCHAR2,

                           actid     IN NUMBER,

                           funcmode  IN VARCHAR2,

                           resultout OUT NOCOPY VARCHAR2) is

  

    l_invoice_id    NUMBER;

    l_approval_memo c_apps.c_customer_invoices_all.approval_memo%TYPE;

    l_approval_id   NUMBER;

  

  begin

    IF (funcmode <> wf_engine.eng_run) THEN

    

      resultout := wf_engine.eng_null;

      RETURN;

    

    END IF;

    l_invoice_id := wf_engine.getitemattrnumber(itemtype => itemtype,

                                                itemkey  => itemkey,

                                                aname    => 'INVOICE_ID');

  

    l_approval_id := wf_engine.getitemattrnumber(itemtype => itemtype,

                                                 itemkey  => itemkey,

                                                 aname    => 'APPROVAL_ID');

  

    l_approval_memo := wf_engine.getitemattrtext(itemtype => itemtype,

                                                 itemkey  => itemkey,

                                                 aname    => 'APPROVAL_MEMO');

  

    UPDATE c_apps.c_customer_invoices_all

       SET approval_id     = l_approval_id,

           approval_date   = sysdate,

           approval_memo   = l_approval_memo,

           approval_status = 'N'

     WHERE invoice_id = l_invoice_id;

    resultout := 'COMPLETE';

  EXCEPTION

    when others then

      wf_core.context('C_CUSTOMER_INVOICE_PKG',

                      'invoice_reject',

                      itemtype,

                      itemkey,

                      TO_CHAR(actid),

                      funcmode,

                      SQLERRM);

      raise;

  end invoice_reject;


end c_customer_invoice_pkg;



最后在PL/SQL中执行

BEGIN

   c_customer_invoice_pkg.insert_data;

end;

查看Event表,记录生成,进入系统,发现Notification已经收到,可以正常审批!

 

 

 

fj.png1.JPG

fj.png2.JPG

fj.png3.JPG

fj.png4.JPG

fj.png5.JPG

fj.png6.JPG

fj.png7.JPG

fj.png8.JPG

fj.png9.JPG

fj.png10.JPG

fj.png11.JPG

fj.png12.JPG

fj.png13.JPG

fj.png14.JPG

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10359218/viewspace-716716/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10359218/viewspace-716716/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值