ZH/Case-Study-01-Journal-31

From ADempiere
Revision as of 23:59, 27 December 2010 by Peanutblake (Talk) (脚本使用问题小结)

Jump to: navigation, search
This Wiki is read-only for reference purposes to avoid broken links.

<返回中文首页> <返回本案例研究首页>

实施日志-31-脚本编写与Rule引擎


2010-12-16

Rule Engine与脚本

  • 今天开始学习和探索Rule Engine(引擎)的Script(脚本编程)。
  • 主要目的:从于从RfQ(询价单)创建Purchase Request(采购申请)。
  • 介绍:ADempiere的Rule窗口可以写脚本,集成了BeanShell。
  • ADempiere的Rule Engine要用到BeanShell,于是了解了一下BeanShell。
  • 相关链接:

讨论栏

2010-12-17

Rule Engine下写脚本

  • 今天把Rule Engine(引擎)的Script弄清楚了。
  • Script Callout主要用于窗体,Script Process主要用于Process。
  • 对于从 询价单 生成 采购申请单,可以利用Script Process执行SQL语句来实现。
 org.compiere.util.DB.executeUpdate(sql, A_TrxName);

脚本使用体会

  1. 优点:脚本的功能很强大。同时脚本既不需要重新编译ADempiere源代码,也不需要重新布署ADempiere服务器,因为脚本规则都存储在数据库中了。
  2. 缺点:不容易进行错误调试。我今天测试的Script当中有个SQL语句语法错误,居然没有任何报错。

对Rule Engine的疑问

  • Rule Engine为什么要区分成不同Event Type?比如Callout与Process,为什么不合并在一起?
  • Rule Engine的Rule Type为什么是JSR 223 Scripting APIs,而不是BeanShell官方网站上JSR 274?
  • A_TrxName的TrxName是什么意思?

弹出对话框

  • Rule Engine中弹出对话框,找到一段代码:
 javax.swing.JOptionPane.showMessageDialog(null,"Doing something in Callout!");
  • 2010年12月28日测试了一下,在C/S下可以正常弹出,但是在B/S下会报错。
  • 能否实现在C/S和B/S都可以弹出对话框?

2010-12-28

自动选择最低报价

界面

  • 今天用Rule引擎编写脚本,实现了一个功能——通过比较价格1与价格2,自动选择最低报价。
  • 自动选择最低报价-询价单明细-网格界面:

自动选择最低报价-询价单明细-网格界面

  • 自动选择最低报价-询价单明细-窗体界面

自动选择最低报价-询价单明细-窗体界面


具体实现

  • Rule引擎:

自动选择最低报价-Rule引擎

  • Search Key: beanshell:C_RfQ_AutoChooseLowerPrice
  • Name: Auto Choose Lower Price in RfQ
  • Description: Auto choose lower price in RfQ Line, by comparing Price 1 with Price 2.
  • Comment/Help: Last update: Dec 28, 2010. Ver 1.1. Peanut
  • Event Type: Callout
  • Rule Type: JSR 223 Scripting APIs
  • Script:
int rowCount = A_Tab.getRowCount(); //统计行数

for(int i = 0; i< rowCount; i++){

   A_Tab.setCurrentRow(i);  //设置为当前行

   int iCompare=A_Tab.getValue("Price").compareTo(A_Tab.getValue("Price2")); //比较价格

   if (iCompare==-1)
      A_Tab.setValue("ChooseQuotation", "A"); // Price 1 < Price 2,则选择供应商A
   else if (iCompare==1)
      A_Tab.setValue("ChooseQuotation", "B"); // Price 1 > Price 2,则选择供应商B
}

result = "";

脚本使用问题小结

Yes/No字段

  • Yes/No字段不能直接赋值给字符字段,要转为String才行,可以使用方法 Boolean.toString() 。示例:
  A_Tab.setValue("Purpose",A_Tab.getValue("SelectBPartnerA").toString()); 

Number对象的处理

  • 对于Number、Cost+Price、Quantity等对象,ADempiere是作为 java.math.BigDecimal 对象处理的。
  • BigDecimal 对象不能像 float 一样 BigDecimal_1 >= BigDecimal_2 来进行比较,而是要通过 BigDecimal.compareTo(BigDecimal val) 方法来比较。
  • 我一开始是直接比较:
 if (A_Tab.getValue("Price") > A_Tab.getValue("Price2") ) 
    A_Tab.setValue("ChooseQuotation", "B");
  • 于是得到错误代码:
===========> GridTab.processCallout:  [12]
javax.script.ScriptException: Sourced file: inline evaluation of: ``int rowCount = A_Tab.getRowCount();
 float priceA; float priceB; for(int i = 0; i . . . '' : Invalid types in binary operator : at Line: 8 :
 in file: inline evaluation of: ``int rowCount = A_Tab.getRowCount(); float priceA; float priceB; 
for(int i = 0; i . . . '' : ) { 
 in inline evaluation of: ``int rowCount = A_Tab.getRowCount(); float priceA; float priceB; for(int 
i = 0; i . . . '' at line number 8
	at bsh.engine.BshScriptEngine.evalSource(BshScriptEngine.java:92)
  • 后来尝试直接转为float:
float priceA=(float) A_Tab.getValue("Price");
float priceB=(float) A_Tab.getValue("Price2");
  • 于是得到错误代码:
java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
caused by: java.lang.ClassCastException: Cannot cast java.math.BigDecimal to float
  • 这时才明白ADempiere将 Number 作为 BigDecimal 对象处理的。要想转为 float 的话可以用 BigDecimal.floatValue() 方法。

脚本使用体会

  1. Script响应速度明显要比编译好的Callout慢。
  2. Script的测试和排错的确不方便。

链接