• 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
    

      

  • 相关阅读:
    C++指针(一)
    探讨mvc下linq多表查询使用viewModel的问题
    利用aspnetPager控件加存储过程实现对gridview的分页
    Javascript 笔记
    对于最近学习WCF的总结——唔聊的服务
    今天面试的一些知识性总结
    使用C#反序列化plist文件
    Running x86 apps on WinRT devices
    ItemsSource绑定中遇到的问题
    字节对齐 详解
  • 原文地址:https://www.cnblogs.com/wsy0202/p/11199586.html
Copyright © 2020-2023  润新知