一、背景
有很多头行结构的form,例如
希望当行上的数量或者单价改变时,头块上的总金额随即更新,而不是需要重新打开form才能看到更新后的数据。
二、问题分析
如果直接使用Form中的SUM属性功能,如果要实现这种及时更新,对于清除等操作要进行复杂处理,Oracle提供了APP_CALCULATE.RUNNING_TOTAL来实现这种需求,封装在APPCORE.PLL中。于是,只要利用重写这个过程,并添加一些触发器就能实现这个功能。(由于最近修改这个问题,结合资料对APP_CALCULATE.RUNNING_TOTAL的介绍和项目上的开发,做了如下总结)
三、开发步骤
1、创建header块的汇总显示字段。由于此合同界面头上有三个字段是显示行上汇总合计的,我们已其中的一个为例,价税合计:TOTAL_AMOUNT_M。
2、在合计显示的数据块中,创建合计项目的汇总临时项目, TOTAL_AMOUNT_M_RTOT_DB,子类信息为/DISPLAY_ITEM。
3、在明细块中创建两个统计使用的item,TOTAL_AMOUNT_RTOT_OLD和TOTAL_AMOUNT_RTOT_DB,子类 DISPLAY_ITEM。
4、调用app_calculate.running_total方法和编写AMOUNT,让其对明细块中的Amount(单价*数量*税率)进行汇总计算。
PROCEDURE RUNNING_TOTAL(EVENT VARCHAR2) IS
BEGIN
APP_CALCULATE.RUNNING_TOTAL(EVENT, 'LINES_V.TAX_VALUE', 'MAIN_V.TOTAL_TAX_AMOUNT_M');
APP_CALCULATE.RUNNING_TOTAL(EVENT, 'LINES_V.TOTAL_AMOUNT', 'MAIN_V.TOTAL_AMOUNT_M');
APP_CALCULATE.RUNNING_TOTAL(EVENT, 'LINES_V.LINE_AMOUNT', 'MAIN_V.TOTAL_LINE_AMOUNT_M');
END RUNNING_TOTAL;
PROCEDURE AMOUNT(EVENT VARCHAR2) IS
BEGIN
IF EVENT = 'INIT'
THEN
--added @20120828:16885]销售合同经常出现金额、税额、价税合计为空或与合同真实信息不一致的情况
IF :Lines_V.Attribute14 IS NOT NULL THEN
--GET TAX RATE
Begin
Select Zrv.Percentage_Rate,Decode(Zrv.inclusive_Tax_Flag,'N','1','2')
Into :Lines_V.Tax_Rate,:Lines_V.INCLUSIVE_TAX_IND
From Zx_Rates_Vl Zrv
Where Zrv.Tax_Rate_Id = To_Number(:Lines_V.Attribute14)
And Sysdate Between Nvl(Zrv.Effective_From, Sysdate - 1) And Nvl(Zrv.Effective_To, Sysdate + 1)
And Zrv.Tax_Status_Code <> 'STAT'
And Zrv.Active_Flag = 'Y';
If Sql%Notfound
Then
:Lines_V.Tax_Rate := Null;
End If;
End;
END IF;
--added end
IF :LINES_V.INCLUSIVE_TAX_IND = 2
THEN
:LINES_V.TAX_VALUE := ROUND(NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0)* (NVL(:LINES_V.TAX_RATE,0) * 0.01 /(NVL(:LINES_V.TAX_RATE,0) * 0.01 + 1)), 2);
:LINES_V.TOTAL_AMOUNT := NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0);--价税合计
:LINES_V.LINE_AMOUNT := NVL(:LINES_V.TOTAL_AMOUNT, 0) - NVL(:LINES_V.TAX_VALUE, 0);--不含税金额
ELSE
:LINES_V.TAX_VALUE := ROUND(NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0) * (NVL(:LINES_V.TAX_RATE, 0) * 0.01), 2);
:LINES_V.TOTAL_AMOUNT := NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0);
:LINES_V.LINE_AMOUNT := NVL(:LINES_V.TOTAL_AMOUNT, 0) - NVL(:LINES_V.TAX_VALUE, 0);
END IF;
END IF;
END AMOUNT;
5、创建数量和单价的WHEN-VALIDATE-ITEM触发器,使其调用app_calculate.running_total运算汇总值。
QUANTITY :
if :system.record_status <> 'QUERY'
THEN
line_item_ctl.amount('INIT');
line_item_ctl.running_total('WHEN-VALIDATE-ITEM');
END IF;
UNIT_SALE_PRICE :
if :system.record_status <> 'QUERY'
THEN
line_item_ctl.amount('INIT');
line_item_ctl.running_total('WHEN-VALIDATE-ITEM');
END IF;
6、在汇总显示项目所在块中的POST-QUERY触发器中从数据库中计算出明细的初始汇总值。
If Event = 'POST-QUERY'
Then
Begin
Select SUM(NVL(COL.UNIT_SALE_PRICE
,0) * NVL(COL.QUANTITY
,0)) TOTAL_AMOUNT
,SUM(DECODE(ZRV.INCLUSIVE_TAX_FLAG
,'N'
,NVL(COL.UNIT_SALE_PRICE
,0) * NVL(COL.QUANTITY
,0) * ZRV.PERCENTAGE_RATE * 0.01
,NVL(COL.UNIT_SALE_PRICE
,0) * NVL(COL.QUANTITY
,0) / 1.17 * ZRV.PERCENTAGE_RATE * 0.01)) TOTAL_TAX_AMOUNT
,SUM(DECODE(ZRV.INCLUSIVE_TAX_FLAG
,'N'
,(NVL(COL.UNIT_SALE_PRICE
,0) * NVL(COL.QUANTITY
,0) + NVL(COL.UNIT_SALE_PRICE
,0) * NVL(COL.QUANTITY
,0) * ZRV.PERCENTAGE_RATE * 0.01)
,(NVL(COL.UNIT_SALE_PRICE
,0) * NVL(COL.QUANTITY
,0) -
NVL(COL.UNIT_SALE_PRICE
,0) * NVL(COL.QUANTITY
,0) / 1.17 * ZRV.PERCENTAGE_RATE * 0.01))) TOTAL_LINE_AMOUNT
/*Into :Main_V.Total_Amount_m
,:Main_V.Total_Tax_Amount_m
,:Main_V.Total_Line_Amount_m*/
--updated @20120911
Into Ln_Total_Amount,
Ln_Total_Tax_Amount,
Ln_Total_Line_Amount
From Cux_Om_Order_Lines_All Col
,Zx_Rates_Vl Zrv
Where Sysdate Between Nvl(Zrv.Effective_From, Sysdate - 1) And Nvl(Zrv.Effective_To, Sysdate + 1)
And Zrv.Tax_Status_Code <> 'STAT'
And Zrv.Active_Flag = 'Y'
And To_Number(Col.Attribute14) = Zrv.Tax_Rate_Id
And Col.Order_Header_Id = :Main_V.Header_Id
And Col.Org_Id = :Main_V.Org_Id
Group By Col.Order_Header_Id
,Col.Org_Id;
Exception
When No_Data_Found Then
Ln_Total_Amount := null;
Ln_Total_Tax_Amount := null;
Ln_Total_Line_Amount := null;
/*:Main_V.Total_Amount_m := Null;
:Main_V.Total_Tax_Amount_m := Null;
:Main_V.Total_Line_Amount_m := Null;*/
End;
:Main_V.Total_Amount_m := Ln_Total_Amount;
:Main_V.Total_Tax_Amount_m := Ln_Total_Tax_Amount;
:Main_V.Total_Line_Amount_m := Ln_Total_Line_Amount;
:Main_V.TOTAL_AMOUNT_M_RTOT_DB := Ln_Total_Amount;
:Main_V.TOTAL_TAX_AMOUNT_M_RTOT_DB := Ln_Total_Tax_Amount;
:Main_V.TOTAL_LINE_AMOUNT_M_RTOT_DB := Ln_Total_Line_Amount;
End If;
7、在明细块的以下触发器中添加相应的代码。
A、KEY-CLRREC
line_item_ctl.running_total('KEY-CLRREC');
B、KEY-DUPREC
DUPLICATE_RECORD;
LINE_ITEM_CTL.RUNNING_TOTAL('KEY-DUPREC');
C、KEY-DELREC
line_item_ctl.running_total('KEY-DELREC');--updated @20120910
Delete_Record;
line_item_ctl.running_total('UNDELETE');--updated @20120910
D、WHEN-CLEAR-BLOCK
line_item_ctl.running_total('WHEN-CLEAR-BLOCK');--added @20120910
F、POST-QUERY
IF :LINES_V.INCLUSIVE_TAX_IND = 2
THEN
:LINES_V.TAX_VALUE := ROUND(NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0)/1.17 * (NVL(:LINES_V.TAX_RATE, 0) * 0.01), 2);
:LINES_V.TOTAL_AMOUNT := NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0);--价税合计
:LINES_V.LINE_AMOUNT := NVL(:LINES_V.TOTAL_AMOUNT, 0) - NVL(:LINES_V.TAX_VALUE, 0);--不含税金额
ELSE
:LINES_V.TAX_VALUE := ROUND(NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0) * (NVL(:LINES_V.TAX_RATE, 0) * 0.01), 2);
:LINES_V.TOTAL_AMOUNT := NVL(:LINES_V.QUANTITY, 0) * NVL(:LINES_V.UNIT_SALE_PRICE, 0);
:LINES_V.LINE_AMOUNT := NVL(:LINES_V.TOTAL_AMOUNT, 0) - NVL(:LINES_V.TAX_VALUE, 0);
END IF;