欢迎光临
我们一直在努力

APP_CALCULATE.RUNNING_TOTAL用法

有时候需要显示某个栏位的汇总数量,且在例如新增、删除、修改记录的时候,汇总项的值要相应地改变,如果直接使用Form中的SUM属性功能,对于清除等操作要进行复杂处理。Oracle提供了APP_CALCULATE.RUNNING_TOTAL来实现这种需求,封装在APPCORE.PLL中。

For Example: 

要汇总的ITEM为:LINES.QUANTITY,要显示汇总结果的BLOCK为HEADERS 

1.HEADERS里建立要显示的汇总结果ITEM,如QTY_SUM 

2.HEADERS里建立两个非数据库项,分别命名为QTY_SUM_RTOT_OLD和QTY_SUM_RTOT_DB(Number型) 

3.LINES里建立两个非数据库项,分别命名为QUANTITY_RTOT_OLD和QUANTITY_RTOT_DB(Number型) 

4.建立存储过程来包装APP_CALCULATE.RUNNING_TOTAL 

例: 

PROCEDURE RUNNING_TOTAL_QUANTITY(EVENT VARCHAR2) IS 

BEGIN 

  APP_CALCULATE.RUNNING_TOTAL(EVENT, 'LINES.QUANTITY', 'HEADERS.QTY_SUM'); 

END; 


–在TRIGGER中调用RUNNING_TOTAL_QUANTITY来进行计算处理 


5.:LINES.QUANTITY的WHEN-VALIDATE-ITEM Trigger中写RUNNING_TOTAL_QUANTITY('WHEN-VALIDATE-ITEM');

    如果要汇总的栏位来自多个栏位的运算,需要在每个栏位的WHEN-VALIDATE-ITEM时写运算重新计算值赋给要汇总的栏位。

6.:HEADERS的POST-QUERY Trigger中从数据库中抓取初始的汇总值,例:

Declare 

  V_SUM NUMBER; 

BEGIN 

  SELECT NVL(SUM(QUANTITY), 0) 

       INTO V_SUM 

     FROM LINES 

   WHERE HEADER_ID = :HEADERS.HEADER_ID; 

  :HEADERS.QTY_SUM                   := V_SUM; 

   

:HEADERS.QTY_SUM_RTOT_DB := V_SUM;———————-注① 


END;

7.:LINES的如下TRIGGER中写相应代码: 

–KEY-DELREC 

RUNNING_TOTAL_QUANTITY('KEY-DELREC'); 

DELETE_RECORD;


RUNNING_TOTAL_QUANTITY('UNDELETE');———————-注③

–KEY-DUPREC 

RUNNING_TOTAL_QUANTITY('KEY-DUPREC'); 

DUPLICATE_RECORD;

–KEY-CLRREC 

RUNNING_TOTAL_QUANTITY('KEY-CLRREC'); 

CLEAR_RECORD;–(网上例子为:APP_FOLDER.EVENT('KEY-CLRREC');)

–POST-QUERY 

RUNNING_TOTAL_QUANTITY( 'POST-QUERY' );


–WHEN-CLEAR-BLOCK 

RUNNING_TOTAL_QUANTITY( 'WHEN-CLEAR-BLOCK' );———————-注②

注:网上例子中还有post_insert,post_update,pre_record中写,我目前没写,测试OK,不知道会有什么漏洞,暂时没测出来。

另外上面的链接中,作者的例子会有问题,像链接文章评论所说,作者需增加 

注① 


的代码 

,即 

WHEN-CLEAR-BLOCK的代码需和注①同时存在(查询发现EBS中PO的画面也是这么做的)。

最初我没有写 

注② 

和 

注① 


的代码 

,后经测试, 


缺少这两部分会出现问题 


,还是举个例子说吧:

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※



例: 

Line项只有一条记录,值为100,


1)正常查询出来记录后,汇总栏显示100;


2)修改记录值为99,汇总栏变为99;


3)按F11,会提示“是否保存记录”,选择“否”;


      –此时汇总栏值为99(正常情况下此时汇总栏显示100)。


4)执行Ctrl+F11;


      –此时汇总栏值依然为99(正常情况下此时汇总栏显示100,(且很大问题是此时Line值为100,汇总为99))。


※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※



所以:注② 



注①一定要写。



注③: 


Block的Delete Allowed设置为No,由于种种原因,Delete按钮是亮的。这种情况下,点击 

Delete按钮 

的时候会提示

            FRM-41049:You cannot delete this record.但是汇总量会被减掉,一直点下去,会一直减掉..直至负NNNN…

            所以加上 


注③,以避免这种情况时汇总量的错误。



至于其它在 

APP_CALCULATE.RUNNING_TOTAL 

中涉及到的 Trigger中是否要写以及如何写,还未测试,目前为止,应用正常。



(有一点问题,即"新增一条记录,保存,然后点击clear-record按钮",数量会减掉,还未解决,其余Trigger应该也需要加上,但是有几个Trigger好像在Block下面没有,但又有其它Trigger调用在它们中产生的全局变量,暂时未过多测试。。Busy。。)







另外,如果汇总结果要拿来与其它值作比较,比如超过了某个值则raise error,则要注意running_total和比较大小两者的先后顺序。



如在when-validate-item时比较,则在此trigger中先running_total,后比较,否则…


————————————————————————————————————————————————–



附APP_CALCULATE.RUNNING_TOTAL原代码:


PACKAGE BODY app_calculate IS


  PROCEDURE running_total(event        VARCHAR2, 

                          source_field VARCHAR2, 

                          total_field  VARCHAR2) IS 

    Last_Val_Field  VARCHAR2(61) := Source_Field || '_RTOT_OLD'; 

    DB_Source_Field VARCHAR2(61) := Source_Field || '_RTOT_DB'; 

    DB_Total_Field  VARCHAR2(61) := Total_Field || '_RTOT_DB'; 

    Last_Value      NUMBER; 

    Source_Value    NUMBER; 

    DB_Source_Value NUMBER; 

    Total_Value     NUMBER := NVL(name_in(Total_Field), 0); 

    DB_Total_Value  NUMBER := NVL(name_in(DB_Total_Field), 0); 

    New_Total       NUMBER; 

    Form_Id         FORMMODULE; 

  BEGIN 

    COPY('Entering app_calculate.running_total.  Event is ' || event || '.', 

         'global.frd_debug'); 

    IF (event <> 'WHEN-CLEAR-BLOCK') THEN 

      Last_Value      := NVL(name_in(Last_Val_Field), 0); 

      Source_Value    := NVL(name_in(Source_Field), 0); 

      DB_Source_Value := NVL(name_in(DB_Source_Field), 0); 

    END IF; 

   

    IF (event = 'POST-QUERY') THEN 

      copy(to_char(Source_Value), DB_Source_Field); 

      copy(to_char(Source_Value), Last_Val_Field); 

     

    ELSIF (event = 'WHEN-CLEAR-BLOCK') THEN 

      IF (Total_Value <> DB_Total_Value) THEN 

        copy(to_char(DB_Total_Value), Total_Field); 

      END IF; 

     

    ELSIF (event = 'WHEN-VALIDATE-ITEM') THEN 

      IF (Source_Value <> Last_Value) THEN 

        New_Total := Total_Value – Last_Value + Source_Value; 

        copy(to_char(New_Total), Total_Field); 

        copy(to_char(Source_Value), Last_Val_Field); 

      END IF; 

     

    ELSIF (event = 'KEY-DELREC') THEN 

      IF (Last_Value <> 0) THEN 

        New_Total := Total_Value – Last_Value; 

        copy(to_char(New_Total), Total_Field); 

      END IF; 

      copy(to_char(Source_Value), Last_Val_Field); 

     

    ELSIF (event IN ('POST-INSERT', 'POST-UPDATE')) THEN 

      IF (Source_Value <> DB_Source_Value) THEN 

        copy(to_char(DB_Source_Value), Last_Val_Field); 

        copy(to_char(Source_Value), DB_Source_Field); 

      END IF; 

     

    ELSIF (event = 'PRE-RECORD') THEN 

      IF (Source_Value <> Last_Value) THEN 

        Form_Id := Find_Form(Get_Application_Property(Current_Form_Name)); 

        IF (Name_In('GLOBAL.RTOT_' || 

                    substr(source_field, 

                           1, 

                           least(instr(source_field, '.') – 1, 15)) || 

                    to_char(Form_id.id)) = 'N') THEN 

          copy(to_char(Last_Value), DB_Source_Field); 

        END IF; 

        copy(to_char(Source_Value), Last_Val_Field); 

      END IF; 

     

    ELSIF (event = 'PRE-COMMIT') THEN 

      Form_Id := Find_Form(Get_Application_Property(Current_Form_Name)); 

      copy('N', 

           'GLOBAL.RTOT_' || 

           substr(source_field, 1, least(instr(source_field, '.') – 1, 15)) || 

           to_char(Form_id.id)); 

     

    ELSIF (event = 'POST-FORMS-COMMIT') THEN 

      Form_Id := Find_Form(Get_Application_Property(Current_Form_Name)); 

      copy('Y', 

           'GLOBAL.RTOT_' || 

           substr(source_field, 1, least(instr(source_field, '.') – 1, 15)) || 

           to_char(Form_id.id)); 

      IF (Total_Value <> DB_Total_Value) THEN 

        copy(to_char(Total_Value), DB_Total_Field); 

      END IF; 

     

    ELSIF (event = 'UNDELETE') THEN 

      New_Total := Total_Value + Source_Value; 

      copy(to_char(New_Total), Total_Field); 

      copy(to_char(Source_Value), Last_Val_Field); 

     

    ELSIF (event = 'KEY-DUPREC') THEN 

      New_Total := Total_Value + Source_Value; 

      copy(to_char(New_Total), Total_Field); 

      copy(to_char(Source_Value), Last_Val_Field); 

      copy(NULL, DB_Source_Field); 

     

    ELSIF (event = 'KEY-CLRREC') THEN 

      IF (Last_Value <> DB_Source_Value) THEN 

        New_Total := Total_Value – Last_Value + DB_Source_Value; 

        copy(to_char(New_Total), Total_Field); 

      END IF; 

    ELSE 

      message('Invalid event ' || event || 

              ' in app_calulate.running_total'); 

    END IF; 

    COPY('Completed app_calculate.running_total.  Event is ' || event || '.', 

         'global.frd_debug'); 

   

  END running_total;


END app_calculate;

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。