Drools 規則學習


Drools 規則學習

在 Drools 當中,一個標准的規則文件就是一個以“.drl”結尾的文本文件,由於它是一
個標准的文本文件,所以可以通過一些記事本工具對其進行打開、查看和編輯。規則是放在
規則文件當中的,一個規則文件可以存放多個規則,除此之外,在規則文件當中還可以存放
用戶自定義的函數、數據對象及自定義查詢等相關在規則當中可能會用到的一些對象。
文件結構圖如下:
package
imports
globals
functions
queries
rules
.....

對於一個規則文件而言,首先聲明 package 是必須的,除 package 之外,其它對象在規
則文件中的順序是任意的,也就是說在規則文件當中必須要有一個 package 聲明,同時
package 聲明必須要放在規則文件的第一行。一個規則通常包括三個部分:屬性部分(attribute) 、條件
部分(LHS)和結果部分(RHS) 一個標准規則的結構如下:
rule "name"
attributes
when
LHS
then
RHS
end

1.在 LHS 當中,可以包含 0~n 個條件,如果 LHS 部分沒空的話,那么引擎會自動添加一個 eval(true)的條件,由於該條件總是返回 true,所以 LHS 為空的規則總是返回 true
2.在這兩個pattern沒有符號連接, 在Drools當中在 pattern 中沒有連接符號,那么就用 and 來作為默認連接,所以在該規則的 LHS 部分中兩個 pattern 只有都滿足了才會返回 true。默認情況下,每行可以用“;”來作為結束符(和Java 的結束一樣) ,當然行尾也可以不加“;”結尾。


條件部分
1.約束連接
對於對象內部的多個約束的連接,可以采用“&&” (and) 、 “||”(or)和“,”(and)來實現
示例代碼:
rule "rule1"
when
Customer(age>20 || gender==’male’&& city==’sh’)
then
<action>…
End

2.比較操作符
在 Drools當中共提供了十二種類型的比較操作符, 分別是: >、 >=、 <、 <=、 = =、 !=、 contains、 not contains、memberof、not memberof、matches、not matches;在這十二種類型的比較操作符當中,前六個是比較常見也是用的比較多的比較操作符
contains 示例代碼:
rule "rule1"
when
$order:Order();
$customer:Customer(age >20, orders contains $order);
then
System.out.println($customer.getName());
end

not contains 示例代碼:
rule "rule1"
when
$order:Order(items not contains "手機");
then
System.out.println($order.getName());
end

memberOf(memberOf 是用來判斷某個 Fact 對象的某個字段是否在一個集合(Collection/Array)當中) 示例代碼:
global String[] orderNames; //定義全局變量
rule "rule1"
when
$order:Order(name memberOf orderNames);
then
System.out.println($order.getName());
end

not memberOf (該操作符與 memberOf 作用洽洽相反) 示例代碼:
rule "rule1"
when
$orderList:String[]();
$order:Order(name not memberOf $orderList);
then
System.out.println($order.getName());
end

matches 是用來對某個 Fact 的字段與標准的 Java 正則表達式進行相似匹配,被比較的字符串可以是一個標准的 Java 正則表達式,但有一點需要注意,那就是正則表達式字符串當中不用考慮“\”的轉義問題。
示例代碼:
rule "rule1"
when
$customer:Customer(name matches "李.*");
then
System.out.println($customer.getName());
end

not matches (該操作符與 matches 作用洽洽相反)

結果部分

我們知道,在規則當中 LHS 就是用來放置條件的,所以在 RHS 當中雖然可以直接編寫
Java 代碼,但不建議在代碼當中有條件判斷,如果需要條件判斷,那么請重新考慮將其放在
LHS 當中,否則就違背了使用規則的初衷

在 Drools 當中,在 RHS 里面,提供了一些對當前 Working Memory 實現快速操作的宏
宏函數或對象, 比如 insert/insertLogical、 update 和 retract 就可以實現對當前 Working Memory
中的 Fact 對象進行新增、刪除或者是修改

1.insert
函數insert的作用與我們在Java類當中調用StatefulKnowledgeSession對象的insert方法的作用相同,都是用來將一個 Fact 對象插入到當前的 Working Memory 當中
需注意:一旦調用 insert 宏函數,那么 Drools 會重新與所有的規則再重新匹配一次, 對於沒有設置no-loop 屬性為 true 的規則,如果條件滿足,不管其之前是否執行過都會再執行一次,這個特性不僅存在於 insert 宏函數上,后面介紹的 update、retract 宏函數同樣具有該特性,所以在某些情況下因考慮不周調用 insert、update 或 retract 容易發生死循環
示例代碼如下:
rule "rule1"
salience 1 //該屬性的作用是通過一個數字來確認規則執行的優先級, 數字越大, 執行越靠前
when
eval(true); //默認成立
then
Customer cus=new Customer();
cus.setName("張三");
insert(cus);
end
rule "rule2"
salience 2
when
$customer:Customer(name =="張三");
then
System.out.println("rule2----"+$customer.getName());
end

2.insertLogical
insertLogical 作用與 insert 類似,它的作用也是將一個 Fact 對象插入到當前的 Working Memroy 當中

3.update
update函數意義與其名稱一樣, 用來實現對當前Working Memory當中的 Fact進行更新,update 宏函數的作用與 StatefulSession 對象的 update 方法的作用基本相同,都是用來告訴當
前的 Working Memory 該 Fact 對象已經發生了變化。它的用法有兩種形式,一種是直接更新一個 Fact 對象,另一種為通過指定 FactHandle 來更新與指定 FactHandle 對應的 Fact 對象
第一種 直接更新一個 Fact 對象:
rule "rule1"
salience 2
when
eval(true);
then
Customer cus=new Customer();
cus.setName("張三");
cus.setAge(1);
insert(cus);
end
rule "rule2"
salience 1
when
$customer:Customer(name=="張三",age<10);
then
$customer.setAge($customer.getAge()+1);
update($customer);
System.out.println("----------"+$customer.getName());
end

第二種 可以支持創建一個新的 Fact 對象, 從而把 FactHandle對象指定的 Fact 對象替換掉,從而實現對象的全新更新:
rule "rule1"
salience 2
when
eval(true);
then
Customer cus=new Customer();
cus.setName("張三");
cus.setAge(1);
insert(cus);
end
rule "rule2"
salience 1
when
$customer:Customer(name=="張三",age<10);
then
Customer customer=new Customer();
customer.setName("張三");
customer.setAge($customer.getAge()+1);
update(drools.getWorkingMemory().getFactHandleByIdentity($customer),customer);
System.out.println("----------"+$customer.getName());
end

4.retract
retract用來將 Working Memory 當中某個 Fact 對象從 Working Memory 當中刪除 示例代碼:
rule "rule1"
salience 2
when
eval(true);
then
Customer cus=new Customer();
cus.setName("張三");
cus.setAge(1);
insert(cus);
end
rule "rule2"
salience 1
when
$customer:Customer(name=="張三");
then
retract($customer);
end
5.modify 
modify是一個表達式塊,它可以快速實現對 Fact 對象多個屬性進行修改,修改完成后會自動更新到當前的 Working Memory 當中
rule "rule1"
salience 2
when
$customer:Customer(name=="張三",age==20);
then
System.out.println("modify before customer
id:"+$customer.getId()+";age:"+$customer.getAge());
modify($customer){
setId("super man"),
setAge(30),
setName("黃五")
}
end
rule "rule2"
salience 1
when
$customer:Customer(name=="黃五");
then
System.out.println("modify after customer
id:"+$customer.getId()+";age:"+$customer.getAge());
end


屬性部分
1.salience
作用是用來設置規則執行的優先級,salience 屬性的值是一個數字,數字越大執行優先級越高,同時它的值可以是一個負數。默認情況下,規則的 salience 默認值為 0,所以如果我們不手動設置規則的 salience 屬性,那么它的執行順序是隨機的。
示例代碼:
rule "rule1"
salience 1
when
eval(true)
then
System.out.println("rule1");
end
rule "rule2"
salience 2
when
eval(true)
then
System.out.println("rule2");
end

雖然 rule1 位於前面,但因為它的 salience 為 1,而 rule2的 salience 屬性為 2,所以 rule2 會先執行,然后 rule1 才會執行。

2.no-loop
作用是用來控制已經執行過的規則在條件再次滿足時是否再次執行。no-loop 屬性的值是一個布爾型,默認情況下規則的 no-loop屬性的值為 false,如果 no-loop 屬性值為 true,那么就表示該規則只會被引擎檢查一次,
如果滿足條件就執行規則的 RHS 部分,如果引擎內部因為對 Fact 更新引起引擎再次啟動檢查規則,那么它會忽略掉所有的 no-loop 屬性設置為 true 的規則。
示例代碼:
rule "rule1"
salience 1
no-loop true
when
$customer:Customer(name=="張三")
then
update($customer);
System.out.println("customer name:"+$customer.getName());
End

3.date-effective
作用是用來控制規則只有在到達后才會觸發,在規則運行時,引擎會自動拿當前操作系統的時候與 date-effective 設置的時間值進行比對, 只有當系統時間>=date-effective 設置的時間值時,
規則才會觸發執行,否則執行將不執行。在沒有設置該屬性的情況下,規則隨時可以觸發,沒有這種限制。date-effective 的值為一個日期型的字符串,默認情況下,date-effective 可接受的日期格式為“dd-MMM-yyyy” 
示例代碼:
rule "rule1"
date-effective "2009-09-25" //當前日期不小於2009-09-25時可以執行
when
eval(true);
then
System.out.println("rule1 is execution!");
end
在實際使用的過程當中,如果您不想用這種時間的格式,那么可以在調用的 Java 代碼中通過使用 System.setProperty(String key,String value)方法來修改默認的時間格式
在java文件中添加此條命令: System.setProperty("drools.dateformat","yyyy-MM-dd");

4.date-expires
作用是與 date-effective 屬性恰恰相反, date-expires 的作用是用來設置規則的有效期,引擎在執行規則的時候,會檢查規則有沒有 date-expires 屬性,如果有的話,那么會將這個屬性的值與當前系統時間進行比對,如果大於系統時間,那么規則就執行,否則就不執行。
示例代碼:
rule "rule1"
date-effective "2009-09-25" //當前日期不小於2009-09-25時可以執行(含2009-09-25) 注意修改時間格式
date-expires "2009-09-30" //當前日期大於2009-09-30時可以執行(不含2009-09-30) 注意修改時間格式
when
eval(true);
then
System.out.println("rule1 is execution!");
end

5.enabled
作用是用來定義一個規則是否可用的。該屬性的值是一個布爾值,默認該屬性的值為 true,表示規則是可用的。設置其 enabled 屬性值為 false,那么引擎就不會執行該規則

6.dialect
作用是用來定義規則當中要使用的語言類型,目前支持兩種類型的語言:mvel 和 java,默認情況下,如果沒有手工設置規則的 dialect,那么使用的 java 語言

7.duration
作用是將在該屬性指定的值之后在另外一個線程里觸發。該屬性對應的值為一個長整型,單位是毫秒
示例代碼:
rule "rule1"
duration 3000
when
eval(true)
then
System.out.println("rule thread id:"+Thread.currentThread().getId());
end

8.lock-on-active
作用是 no-loop 的增強版屬性,它主要作用在使用 ruleflow-group 屬性或 agenda-group 屬性的時候。lock-on-active 屬性默認值為 false。
9.activation-group
作用是將若干個規則划分成一個組,用一個字符串來給這個組命名,這樣在執行的時候,具有相同 activation-group 屬性的規則中只要有一個會被執行,其它的規則都將不再執行。
也就是說,在一組具有相同 activation-group 屬性的規則當中,只有一個規則會被執行,其它規則都將不會被執行。當然對於具有相同 activation-group 屬性的規則當中究竟哪一個會先執行,則可以用類似 salience 之類屬性來實現。
示例代碼:
rule "rule1"
activation-group "test"
when
eval(true)
then
System.out.println("rule1 execute");
end
rule "rule 2"
activation-group "test"
when
eval(true)
then
System.out.println("rule2 execute");
end

10.agenda-group
作用是agenda-group 屬性的值也是一個字符串,通過這個字符串,可以將規則分為若干個Agenda Group,默認情況下,引擎在調用這些設置了 agenda-group 屬性的規則的時候需要顯
示的指定某個 Agenda Group 得到 Focus (焦點) , 這樣位於該 Agenda Group 當中的規則才會觸發執行,否則將不執行。
示例代碼:
rule "rule1"
agenda-group "001"
when
eval(true)
then
System.out.println("rule1 execute");
end
rule "rule 2"
agenda-group "002"
when
eval(true)
then
System.out.println("rule2 execute");
end
java調用:
StatefulKnowledgeSession statefulSession = knowledgeBase.newStatefulKnowledgeSession();
statefulSession.getAgenda().getAgendaGroup("002").setFocus(); //獲得執行焦點
statefulSession.fireAllRules();
statefulSession.dispose();

//了解即可 不常用

11.auto-focus
作用是用來在已設置了 agenda-group 的規則上設置該規則是否可以自動獨取 Focus,如果該屬性設置為 true,那么在引擎執行時,就不需要顯示的為某個 Agenda Group 設置 Focus,否則需要。
12.ruleflow-group
作用是用來將規則划分為一個個的組,然后在規則流當中通過使用 ruleflow-group 屬性的值,從而使用對應的規則。

實例如下:

#created on: 2012-04-13
#updated on: 2012-06-01
package mcs.fee;

import java.math.BigDecimal;
import mcs.clear.ClearTxnList;
import mcs.fee.FeeContext;
import mcs.fee.FeeUtil;
import mcs.clear.FeeReturn;
import mcs.clear.ClearTxnListLeg;
import mas.bin.CardTypes;
import mas.transaction.TxnCtrlTunnelDataTagNames;

function boolean isFeeParamExists(FeeContext fc, String paramName) {
	return (fc.getFeeContract().getParameter(paramName) != null);
}

function void setMinFee(FeeContext fc, ClearTxnList ctl, BigDecimal fee) {
	BigDecimal minFee = fc.getBigDecimal("min_fee");
	if(fee.abs().compareTo(minFee) < 0) {
		ctl.setFee(minFee.negate());
	} else {
		ctl.setFee(fee);
	}
}

function boolean isDebitCardType(ClearTxnList ctl){
    if(CardTypes.DEBIT_CARD.equals(ctl.getCardType())){
      return true;
    }
    return false;
}

# 判斷是否為飛凡通,若是非凡通,則飛凡通優惠規則
function boolean isDiscountType(ClearTxnList ctl){
	
	Boolean discountRate = ctl.getTunnelData("discountRate") == null ? null : (Boolean) ctl.getTunnelData("discountRate");
	if (discountRate != null && "true".equals(discountRate.toString())) {
			return true;
		}
	return false;
}

# To Negative Number
function BigDecimal toNegNum(BigDecimal num) {
	return (num.signum() > 0 ? num.negate() : num);
}

# Common - getMCC
function String getMCC(ClearTxnList ctl) {
	return (ctl.getAuthMCC() != null ? ctl.getAuthMCC() : ctl.getMCC());
}

#是否日常消費行業MCC true:是,false:否
function boolean isDailyConsumeMCC(String mcc){
	#非日常消費mcc
	String notDailyConsumeMcc = "9498,5094,6010,6011,6051,1520,1771,5271,7013,5511,5521,5551,5561,5571,5592,5598,5599,5933"
	+",6012,4011,4214,4458,5013,5021,5039,5044,5045,5046,5047,5051,5065,5072,5074,5111,5122,5131,5137,5139,5172,5192,5193"
	+",5198,5398,5998";
	
	if(notDailyConsumeMcc.indexOf(mcc) > -1){
		return false;
	}
	
	return true;
}

#是否二維碼優惠 true:是,false:否
function boolean isQRCodeDiscount(ClearTxnList ctl){
	#交易金額
	BigDecimal amt = ctl.getAmt();
	#最大優惠金額
	BigDecimal topDiscAmt = new BigDecimal("1000.00");
	if(topDiscAmt.compareTo(amt)>-1){
		return true;
	}
	return false;
}

#封頂值比較,超過封頂值為true, 否則為false
function boolean topFeeCompare(BigDecimal fee, BigDecimal topFee) {
	if(fee == null || topFee == null) {
	    return false;
	}
	if(fee.abs().compareTo(topFee.abs())>0) {
	    return true;
	}
	return false;
}

rule "Settle Rule for Authenticate Txn"
	activation-group "Fee by CardOrg"
	salience 16
	no-loop
	when
		$cl : ClearTxnList(txnType == "00L00")
		$fc : FeeContext ()
	then
		if($fc.getFeeContract().getParameter("indauth_fee") != null){
			$cl.setFee($fc.getBigDecimal("indauth_fee"));
		}else{
			$cl.setFee(BigDecimal.ZERO);
		}
end

rule "Settle Rule 00 for appType"
	activation-group "Fee by CardOrg"
	salience 15
	no-loop
	when
		$cl : ClearTxnList()
		$fc : FeeContext ()
		eval ( FeeUtil.isBpsSWZF($cl.getAppType()) )		
	then
		String  appType = $cl.getAppType().toLowerCase() ;
		$cl.setFeeRate($fc.getBigDecimal(appType+"_cu_rate"));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 00 for APPLE PAY"
	activation-group "Fee by CardOrg"
	salience 14
	no-loop
	when
		$cl : ClearTxnList( txnType == "20200", appType == "APPLEPAY" )
		$fc : FeeContext ()
	then
		BigDecimal feeRate = null;
		BigDecimal topFee = null;
		String discModeFlag = $fc.getString("cuqrcode_spec_disc_mode");
		if( isQRCodeDiscount($cl) && isDailyConsumeMCC(getMCC($cl))  && !"1".equals(discModeFlag) ){
	      feeRate = $fc.getBigDecimal("applepay_disc_rate");
	    } else {
	    	#借記卡
	    	if( isDebitCardType($cl) ){
		  	  feeRate = $fc.getBigDecimal("applepay_debit_rate");
		  	  #封頂值
		      topFee = $fc.getBigDecimal("applepay_debit_max_fee");
			  BigDecimal fee = FeeUtil.calcFee($cl.getAmt(), feeRate);
			  if( topFeeCompare(fee, topFee) ){
					fee = toNegNum(topFee);
				}
			  $cl.setFee(fee);
	    	} else {#貸記卡
	    	  feeRate = $fc.getBigDecimal("applepay_credit_rate");
	    	}
	    }
	    
		$cl.setFeeRate(feeRate);
end

rule "Settle Rule 061 for FFANT aggregate pay"
	activation-group "Fee by CardOrg"
	salience 13
	no-loop
	when
		$cl : ClearTxnList( serviceChannelType == "J", serviceChannelSrc == 'Z' )
		$fc : FeeContext ();
	then
		String prodCode = String.valueOf($cl.getTunnelData("FFANT_PROD_CODE")).toLowerCase();
		$cl.setFeeRate($fc.getBigDecimal($cl.getAppType().toLowerCase() +"_" + prodCode + "_rate"));
end

rule "Settle Rule 00 for wallet"
	activation-group "Fee by CardOrg"
	salience 12
	no-loop
	when
		$cl : ClearTxnList( txnType == "20200" )
		$fc : FeeContext ();
	then
	
	  String appType = $cl.getAppType();
	  String serviceChannelType = $cl.getServiceChannelType();
	  String serviceChannelSrc = $cl.getServiceChannelSrc();
		
	  if(FeeUtil.isAggregatePay(serviceChannelType, serviceChannelSrc)){
		  $cl.setFeeRate($fc.getBigDecimal(appType.toLowerCase() + "_" + serviceChannelType.toLowerCase() + "_" + serviceChannelSrc.toLowerCase()  + "_rate"));
	  }else{
	     $cl.setFeeRate($fc.getBigDecimal((appType.toLowerCase()).replace("csb","") + "_wallet_rate"));
	  }
end

rule "Settle Rule 00 for ValueAddTxn"
	activation-group "Fee by CardOrg"
	salience 11
	no-loop
	when
		$cl : ClearTxnList( valueAddTxnFlag == true )
		$fc : FeeContext ();
	then
		$cl.setFee($fc.getBigDecimal("va_fee").negate());
		$cl.setFeeRate(null);
end

rule "Settle Rule 00 for QuickRefund with OrigTxn"
	activation-group "Fee by CardOrg"
	salience 10
	no-loop
	when
		$cl : ClearTxnList( txnType == "00500", quickRefundFlag == true )
		$origCl : ClearTxnList ( txnType != "00500" )
		$fc : FeeContext ()
	then
		ClearTxnListLeg leg = new ClearTxnListLeg();
		leg.setSettleMerchantId($cl.getSettleMerchantId());
		leg.setValueDate($cl.getValueDate());
		leg.setFee($fc.getBigDecimal("qk_rfd_fee"));
		leg.setFeePercent(null);
		leg.setAmt(BigDecimal.ZERO);
		$cl.addLeg(leg);
		
		BigDecimal percent = $cl.getAmt().divide($origCl.getAmt(), 6, BigDecimal.ROUND_HALF_UP);
		$cl.setFee($origCl.getFee().multiply(percent).setScale(2, BigDecimal.ROUND_HALF_UP));
		$cl.setFeeRate($origCl.getFeeRate());
end

rule "Settle Rule 00 for QuickRefund"
	activation-group "Fee by CardOrg"
	salience 9
	no-loop
	when
		$cl : ClearTxnList( txnType == "00500", quickRefundFlag == true )
		$fc : FeeContext ()
	then
		ClearTxnListLeg leg = new ClearTxnListLeg();
		leg.setSettleMerchantId($cl.getSettleMerchantId());
		leg.setValueDate($cl.getValueDate());
		leg.setFee($fc.getBigDecimal("qk_rfd_fee"));
		leg.setFeePercent(null);
		leg.setAmt(BigDecimal.ZERO);
		$cl.addLeg(leg);
end

rule "Settle Rule 00 for MBP Txn"
	activation-group "Fee by CardOrg"
	salience 8
	no-loop true
	when
		$cl : ClearTxnList(txnType == "00200",serviceChannelType =="L",serviceEntryMode matches "02.")
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("cu_rate"));
		BigDecimal mbpFixedFee = $fc.getBigDecimal("mbp_fixed_fee");
		if($cl.getTunnelData("quick.pay.txn.fee_flag") != null && "0".equals($cl.getTunnelData("quick.pay.txn.fee_flag").toString())){
			mbpFixedFee = new BigDecimal(0);
		}
		
		$cl.setFee(mbpFixedFee.negate().add(FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate())));

		if(isFeeParamExists( $fc, "min_fee" )){
			setMinFee($fc, $cl, $cl.getFee());
		}
end

rule "Settle Rule 02 for IVR CU"
	activation-group "Fee by CardOrg"
	salience 7
	no-loop true
	when
		$cl : ClearTxnList( serviceConditionCode == "20", cardOrg == "CU" )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("ivr_rate"));
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 00 for AUTH_PUR CU"
	activation-group "Fee by CardOrg"
	salience 6
	no-loop true
	when
		$cl : ClearTxnList( appType == "CPS_AUTH_PUR", cardOrg == "CU" )
		$fc : FeeContext ()
		eval ( isFeeParamExists ( $fc, "auth_pur_rate" ) )
	then
		$cl.setFeeRate($fc.getBigDecimal("auth_pur_rate"));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 00 for CardOrg UT"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ClearTxnList( cardOrg == "UT" )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("ut_rate"));

		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 01 for CardOrg CU"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ClearTxnList( txnType != "00400", cardOrg == "CU" )
		$fc : FeeContext ();
	then
		if(($cl.getTunnelData("isICCard")!=null)&&(((String)$cl.getTunnelData("isICCard")).equals("true"))&&($fc.getFeeContract().getParameter("cu_ic_rate")!=null)){
			$cl.setFeeRate($fc.getBigDecimal("cu_ic_rate"));
		}else{
			$cl.setFeeRate($fc.getBigDecimal("cu_rate"));
		}
		
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 011 for CardOrg CU"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ClearTxnList( txnType == "00400", cardOrg == "CU" )
		$fc : FeeContext ();
	then
		if(($cl.getTunnelData("isICCard")!=null)&&(((String)$cl.getTunnelData("isICCard")).equals("true"))&&($fc.getFeeContract().getParameter("cu_ic_rate")!=null)){
			$cl.setFeeRate($fc.getBigDecimal("cu_ic_rate"));
			$cl.setFee(FeeUtil.calcFeeWithReturn($cl.getAmt(), $fc.getBigDecimal("cu_ic_rate"), $fc.getBigDecimal("va_fee")));
		}else{
			$cl.setFeeRate($fc.getBigDecimal("cu_rate"));
			$cl.setFee(FeeUtil.calcFeeWithReturn($cl.getAmt(), $fc.getBigDecimal("cu_rate"), $fc.getBigDecimal("va_fee")));
		}
		
		if(isFeeParamExists( $fc, "min_fee" )){
			setMinFee($fc, $cl, $cl.getFee());
		}
end

rule "Settle Rule 02 for CardOrg PC"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ClearTxnList( txnType != "00400", cardOrg == "PC" )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("svc_rate"));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 021 for CardOrg PC"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ClearTxnList( txnType == "00400", cardOrg == "PC" )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("svc_rate"));
		$cl.setFee(FeeUtil.calcFeeWithReturn($cl.getAmt(), $fc.getBigDecimal("svc_rate"), $fc.getBigDecimal("va_fee")));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			setMinFee($fc, $cl, $cl.getFee());
		}
end

rule "Settle Rule 03 for CardOrg AX DC JCB"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ( ClearTxnList( txnType != "00400", cardOrg == "AX" ) or ClearTxnList( txnType != "00400", cardOrg == "DC" ) or ClearTxnList( txnType != "00400", cardOrg == "JC" ) )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("adj_rate"));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 031 for CardOrg AX DC JCB"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ( ClearTxnList( txnType == "00400", cardOrg == "AX" ) or ClearTxnList( txnType == "00400", cardOrg == "DC" ) or ClearTxnList( txnType == "00400", cardOrg == "JC" ) )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("adj_rate"));
		$cl.setFee(FeeUtil.calcFeeWithReturn($cl.getAmt(), $fc.getBigDecimal("adj_rate"), $fc.getBigDecimal("va_fee")));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			setMinFee($fc, $cl, $cl.getFee());
		}
end

rule "Settle Rule 04 for CardOrg VI MC"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ( ClearTxnList( txnType != "00400", cardOrg == "VI" ) or ClearTxnList( txnType != "00400", cardOrg == "MC" ) )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("vm_rate"));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 041 for CardOrg VI MC"
	activation-group "Fee by CardOrg"
	no-loop true
	when
		$cl : ( ClearTxnList( txnType == "00400", cardOrg == "VI" ) or ClearTxnList( txnType == "00400", cardOrg == "MC" ) )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("vm_rate"));
		$cl.setFee(FeeUtil.calcFeeWithReturn($cl.getAmt(), $fc.getBigDecimal("vm_rate"), $fc.getBigDecimal("va_fee")));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			setMinFee($fc, $cl, $cl.getFee());
		}
end

rule "Settle Rule 05 for CardOrg EP"
	activation-group "Fee by CardOrg"
	when
		$cl : ( ClearTxnList( txnType != "00400", cardOrg == "EP" ) )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("eap_rate"));
		
		if(isFeeParamExists( $fc, "min_fee" )){
			BigDecimal fee = FeeUtil.calcFee($cl.getAmt(),$cl.getFeeRate());
			setMinFee($fc, $cl, fee);
		}
end

rule "Settle Rule 051 for CardOrg EP"
	activation-group "Fee by CardOrg"
	when
		$cl : ( ClearTxnList( txnType == "00400", cardOrg == "EP" ) )
		$fc : FeeContext ();
	then
		$cl.setFeeRate($fc.getBigDecimal("eap_rate"));
		$cl.setFee(FeeUtil.calcFeeWithReturn($cl.getAmt(), $fc.getBigDecimal("eap_rate"), $fc.getBigDecimal("va_fee")));

		if(isFeeParamExists( $fc, "min_fee" )){
			setMinFee($fc, $cl, $cl.getFee());
		}
end

rule "Settle Rule 06 for TxnType"
	activation-group "Advance Fee by TxnType"
	salience -1
	when
		$cl : ( ClearTxnList( txnType == "00200")  or ClearTxnList( txnType == "20200") )
		$fc : FeeContext ();
	then
		if($cl.getStpFlag() != null && $cl.getStpFlag().booleanValue()){
			BigDecimal stpRate = $fc.getBigDecimal("stp_rate") ;
			if(stpRate != null && !stpRate.equals(BigDecimal.ZERO)){
				BigDecimal stpFee = FeeUtil.calcFee($cl.getAmt(),stpRate);
				FeeUtil.setFeeAndFeeRate($cl,stpFee,stpRate);
			}
		}else if("1".equals($cl.getTunnelData(TxnCtrlTunnelDataTagNames.STL_HOLIDAY))){
			BigDecimal holidayRate  = $fc.getBigDecimal("holiday_rate") ;
			if(holidayRate != null && !holidayRate.equals(BigDecimal.ZERO)){
				BigDecimal holidayFee = FeeUtil.calcFee($cl.getAmt(),holidayRate);
				FeeUtil.setFeeAndFeeRate($cl,holidayFee,holidayRate);
			}
		}
end

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM