EBS 实现主从关系Form中汇总行金额/数量

在Oracle EBS的二次开发中,常有在主从关系的主块中需要显示明细块中金额或数量的汇总,在Oracle Form. Builder中实际上提供了汇总的功能,但它的这个汇总功能的前提是汇总的明细块需要一次性查询出所有的数据,这对于基于B/S架构的EBS应用来说显然是不合适的,因此Oracle专门包装了一个汇总计算的方法app_calculate.running_total 来解决这个问题。

下面以实际的例子来描述如何实现汇总计算,效果图如下:

背景说明:
1.头上面的Salary_Total汇总行上面的Salary
2.行上面的Salary会影响到Salary_Total值的改变

实现步骤:
1.创建合计显示字段:SALARY_TOTAL 设置其子类属性为:TEXT_ITEM_DISPLAY_ONLY
2,在合计显示的数据块中,创建合计项目的汇总临时项目,命名规则为:_RTOT_DB,NUMBER(38)/DISPLAY_ITEM,即SALARY_TOTAL_RTOT_DB/NUMBER(38)/DISPLAY_ITEM

3,在明细块中创建两个统计使用的item,一个_RTOT_OLD,另一个_RTOT_DB,类型 NUMBER(61) DISPLAY_ITEM,即SALARY_RTOT_OLD/NUMBER(61)/DISPLAY_ITEM 和 SALARY_RTOT_DB/NUMBER(61)/DISPLAY_ITEM

4.包装一下APP_CALCULATE.RUNNING_TOTAL方法,让其对行中的Salary进行汇总计算

PROCEDURE RUNNING_TOTAL_SALARY(event varchar2) IS
BEGIN
 APP_CALCULATE.RUNNING_TOTAL(EVENT, 'EMPLOYEES.SALARY', 'DEPARTMENTS.SALARY_TOTAL'); 
END;

在TRIGGER中调用RUNNING_TOTAL_QUANTITY来进行计算处理
5.:EMPLOYEES.SALARY的WHEN-VALIDATE-ITEM Trigger中写RUNNING_TOTAL_SALARY('WHEN-VALIDATE-ITEM');

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

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

Declare 
  V_SUM NUMBER; 
BEGIN 
  SELECT NVL(SUM(SALARY), 0) 
       INTO V_SUM 
     FROM CUX_EMPLOYEES_V 
   WHERE DEPARTMENT_ID = :DEPARTMENTS.DEPARTMENT_ID; 
   :DEPARTMENTS.SALARY_TOTAL     := V_SUM; 
   :DEPARTMENTS.SALARY_TOTAL_RTOT_DB := V_SUM;----------------------注① 
END;

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

--KEY-DELREC 
RUNNING_TOTAL_SALARY('KEY-DELREC'); 
DELETE_RECORD;

RUNNING_TOTAL_SALARY('UNDELETE');----------------------注③

--KEY-DUPREC 
RUNNING_TOTAL_SALARY('KEY-DUPREC'); 
DUPLICATE_RECORD;

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

--POST-QUERY 
RUNNING_TOTAL_SALARY( 'POST-QUERY' );

--WHEN-CLEAR-BLOCK 
RUNNING_TOTAL_SALARY( 'WHEN-CLEAR-BLOCK' );----------------------注②

附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;

参考文档:
在Oracle EBS的二次开发中,常有在主从关系的主块中需要显示明细块中金额或数量的汇总,在Oracle Form. Builder中实际上提供了汇总的功能,但它的这个汇总功能的前提是汇总的明细块需要一次性查询出所有的数据,这对于基于B/S架构的EBS应用来说显然是不合适的,因此Oracle专门包装了一个汇总计算的方法app_calculate.running_total 来解决这个问题。

下面以实际的例子来描述如何实现汇总计算,效果图如下:

背景说明:

头块中的Total字段(HEADERS.AMOUNT_TOTAL)汇总行上面Amount(LINES.AMOUNT)
行中的Amount是Unit Price(lines.unit_price)和Quantity(lines.quantity)的乘积
Unit Price和Quantity的任何更改会导致Amount发生改变,最终影响Total值
实现步骤:

1,创建合计显示字段,即HEADERS.AMOUNT_TOTAL,设置其子类属性为:TEXT_ITEM_DISPLAY_ONLY

2,在合计显示的数据块中,创建合计项目的汇总临时项目,命名规则为:_RTOT_DB,NUMBER(38)/DISPLAY_ITEM,即AMOUNT_RTOT_DB/NUMBER(38)/DISPLAY_ITEM

3,在明细块中创建两个统计使用的item,一个_RTOT_OLD,另一个_RTOT_DB,类型 CHAR(61) DISPLAY_ITEM,即AMOUNT_RTOT_OLD/CHAR(61)/DISPLAY_ITEM 和 AMOUNT_RTOT_DB/CHAR(61)/DISPLAY_ITEM

4,包装一下app_calculate.running_total方法,让其对明细块中的Amount进行汇总计算

procedure running_total (event varchar2) is
begin
app_calculate.running_total(event,'LINES.AMOUNT','HEADERS.AMOUNT_TOTAL');
end running_total;

5,在引发Amount变化的两个Item的WHEN-VALIDATE-ITEM触发器中调用app_calculate.running_total运算汇总值,Item的Handler代码如下:

procedure unit_price (event varchar2) is
begin
if event = 'WHEN-VALIDATE-ITEM' then
lines.amount('INIT');
lines.running_total('WHEN-VALIDATE-ITEM');
end if;
end unit_price;


procedure quantity (event varchar2) is
begin
if event = 'WHEN-VALIDATE-ITEM' then
lines.amount('INIT');
lines.running_total('WHEN-VALIDATE-ITEM');
end if;
end quantity;

6,创建Amount的Handler代码

procedure amount (event varchar2) is
begin
if event = 'INIT' then
copy(name_in('lines.unit_price') * name_in('lines.quantity'),'lines.amount');
end if;
end amount;

7,在汇总显示项目所在块中的POST-QUERY触发器中从数据库中计算出明细的初始汇总值

procedure post_query is
begin
select nvl(sum(unit_price*quantity),0)
into :headers.amount_total
from xhu_order_lines
where header_id = :headers.header_id ;
end post_query;

8,在明细块的以下触发器中添加相应的代码

--KEY-DELREC
lines.running_total('KEY-DELREC');
Delete_Record;
--KEY-DUPREC
lines.running_total('KEY-DUPREC');
duplicate_record;
--KEY-CLRREC
lines.running_total('KEY-CLRREC');
app_folder.event('KEY-CLRREC');
--WHEN-CLEAR-BLOCK
lines.running_total('WHEN-CLEAR-BLOCK');
--POST-QUERY
lines.running_total( 'POST-QUERY' );
posted @   胖大海527  阅读(232)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示