在用友系列的软件中经常可以看到可配置的计算公式,AX中其实也有可配置的公式,如call center呼叫中心的欺诈Fraud rule的配置,AX后台可以根据配置规则,变量,条件来动态产生方法并执行,如下:
public static boolean executeRule(MCRUpSellRule _rule, RecId _salesLineRecId)
{
str condition;
str andOr;
MCRUpSellVarRule mcrUpSellVarRule;
MCRUpSellVarRuleDetail mcrUpSellVarRuleDetail;
//BP Deviation Documented
XppCompiler xppCompiler;
MCRFraudRule mcrFraudRule;
MCRUpSellRule rule = _rule;
new ExecutePermission().assert();
// BP Deviation Documented
xppCompiler = new xppCompiler();
condition = "";
andOr = "";
while select Operand, LeftParen, RightParen, ConditionName from mcrUpSellVarRuleDetail where mcrUpSellVarRuleDetail.RuleID == rule
{
switch (mcrUpSellVarRuleDetail.Operand)
{
case MCRUpSellOperandType::None: andOr = ""; break;
case MCRUpSellOperandType::AND: andOr = ' && '; break;
case MCRUpSellOperandType::OR: andOr = ' || '; break;
}
condition = condition
+ enum2str(mcrUpSellVarRuleDetail.LeftParen)
+ 'MCRUpSellCrossSell::executeCondition('
+ strfmt('%1', _salesLineRecId) + ', \''
+ mcrUpSellVarRuleDetail.ConditionName + '\')'
+ enum2str(mcrUpSellVarRuleDetail.RightParen) + andOr;
}
condition = 'boolean retstuff(){ return ' + condition + '; }';
xppCompiler.compile(condition);
if (xppCompiler.errorText() != "")
{
select firstOnly RecId from mcrUpSellVarRule
where mcrUpSellVarRule.RuleID == rule;
select firstonly RecId from mcrFraudRule
where mcrFraudRule.RuleId == rule;
if (!mcrUpSellVarRule && !mcrFraudRule)
{
error(strfmt("@MCR11882", rule));
}
else
{
if (mcrFraudRule)
{
rule = MCRFraudRule::find(rule).RuleName;
error(strfmt("@MCR24889", rule, xppCompiler.errorText()));
}
else //the problem is with an upsellCrossSell Rule
{
error(strfmt("@MCR11883", rule, xppCompiler.errorText()));
}
}
return false;
}
return xppCompiler.execute();
}
配置规则里的逻辑不复杂,下面例子说明,如果创建带参数的动态方法:
new ExecutePermission().assert();
xppCompiler = new XppCompiler();
condition = '';
condition = strFmt(this.Notes,
enum2int(curSettlement.PurchCoalIncentiveClaims),
num2str(curDetails.PurchQty,0,2,0,0),
num2str(curDetails.PurchPrice,0,2,0,0),
num2str(this.LoadPortValue,0,2,0,0),
num2str(this.UnLoadPortValue,0,2,0,0),
num2str(this.LowerLimit,0,2,0,0),
num2str(this.UpperLimit,0,2,0,0));
xppCompiler.compile(condition);
if (xppCompiler.errorText() != '')
error(strfmt("@HVL1634",xppCompiler.errorText()));
return xppCompiler.execute();
this.Notes的方法体如下,其中%1表示接收第一个参数.
public LineAmount executeFormula( )
{
LineAmount curLineAmount1,curLineAmount2;
;
if(%4 ==0)
{
curLineAmount1 = 0;
curLineAmount2 = 0;
}
else
{
curLineAmount1 = decRound((%4-%6)*decRound(%3/%6,3),2)*%2;
curLineAmount2= (%4>=(%6-200) ? 0 : (%4-%6-200)*decRound(%3/%6,3))*%2;
}
return decRound(curLineAmount1+curLineAmount2,2) ;
}
以下例子也可以参考
http://www.van-veldhuizen.eu/blog/2012/04/19/run-custom-code-microsoft-dynamics-ax-2012/
n previous versions we used the RunBuff() method to run configured scripts. This is not allowed when you run in CIL.
There is a simple work around as there is new class: XppCompiler
http://msdn.microsoft.com/en-us/library/xppcompiler.executeex.aspx
A small sample is shown below:
static void Job12(Args _args)
{
XppCompiler compiler = new XppCompiler();
source source = strFmt("anyType runMethod()\n{\n return %1\n}\n", 'today();');
;
compiler.compile(source);
test = compiler.execute();
}