和以前的版本一样,AX2012中很多地方都使用财务维度,比如客户、销售订单、销售订单行等,根据相应的财务维度设置,生成的相应财务分录将带有财务维度,方便后续对财务分录交易的分析。下图是在客户记录上设置默认财务维度的情况:
默认财务维度只包括CostCenter、Department和ExpensePurpose,如果要象上图要添加显示其他的财务维度,在以前的版本中需要编程实现,但是在AX2012我们只需要配置即可实现。
首先需要创建相应的财务维度(General ledger>Setup>Financial dimensions>Financial dimensions,表DimensionAttribute的一条记录对应一个财务维度):
需要注意的是“use values from”选项,系统集成了几种维度值来源,比如这里维度“Customer”的维度取值为“Customers”,维度的值将来自于CustTable表由系统自动生成不能手工添加(其实来自于视图DimAttributeCustTable)。“use values from”可以是“<Custom dimension>”,这种维度的维度值是手工维护的,点击“Financial dimension values”可以维护维度的值列表:
维度“Customer”取值来自于系统,所以上图中是不能修改维度取值的,“new”、“delete”等按钮是灰化的。
创建的财务维度我们需要添加到相应公司的总账账号结构中,找到General ledger>Setup>Ledger:
Account structures有两条记录,选择一条记录点击“Config account structure”:
上图中我们把“Customer”和“Vendor”添加到默认的总账账号结构中,激活后我们在客户记录的默认财务维度中就能看到“Customer”和“Vendor”两个维度了。
再来看看相关的数据是如何保存的,客户表CusTable.DefaultDimension保存的是来自于DimensionAttributeValueSet表的一条记录RecId,表单上维度信息的显示与编辑由类DimensionDefaultingController实现,它用下面的代码根据DimensionAttributeValueSet.RecId获取各个维度的设置值:
protected container getAttributeValueSet(DimensionDefault _dimAttributeValueSetId, selectableDataArea _company) { return DimensionControllerObject::getAttributeValueSetServer(_dimAttributeValueSetId, _company); }
这里用到另外一个表DimensionAttributeValueSetItem,假设我们在图1中同时设置客户的Department和Department两个财务维度,这个过程会创建1条DimensionAttributeValueSet记录和2条DimensionAttributeValueSetItem记录:
- DimensionAttributeValueSetItem.DimensionAttributeValueSet 字段 -> DimensionAttributeValueSet.RecId
- DimensionAttributeValueSetItem.DimensionAttributeValue 字段 -> DimensionAttributeValue.RecId (该表的一条记录保存财务维度的一个取值)
- DimensionAttributeValue.DimensionAttribute 字段 -> DimensionAttribute.RecId
通过关联查询这几个表,我们就能查找出CustTable.DefaultDimension所代表的一组Dimension及其值的组合。DimensionAttributeValueSet表只有一个字段Hash,且被设置为不能重复的索引,它表示的是其代表的一组维度值HashKey经过运算后得到的哈希值,存放在表DimensionAttributeValueSet以表示这样的财务组合已经存在,以防止重复生成相应的维度组合。
在有一定的了解后,我们来看看如何通过代码设置默认维度:
static void setCustTableDefaultFinancialDimension(Args _args) { #LedgerSHA1Hash DimensionSHA1Hash hash; //To store the calculated hash for DimensionAttributeValueSet HashKey valueKeyHashArray[]; //To store the has key of dimension in question Map dimAttrIdx; //to store the dimension index and backing entity type DimensionAttributeSetItem dimAttrSetItem; // Contains the number of dimensions active for a account structure ledger DimensionAttribute dimAttr; // Contains the financial dimensions records DimensionAttributeValue dimAttrValue; // Contains used financial dimension values DimensionAttributeValueSet dimAttrValueSet; //Contains default dimension records DimensionAttributeValueSetItem dimAttrValueSetItem; //Contains individual records for default dimensions DimAttributeCustTable dimAttrCustTable; //Backing entity view for Employee type dimension DimensionEnumeration dimensionSetId; //Record id for table that contains active dimensions for current ledger CustTable custTable; //Record of the customer used to set the dimension int dimAttrCount, i; int custBackEntityType; //Stores the backing entity type for Employee type dimension ; //The employee backing entity will be the view DimAttributeHcmWorker custBackEntityType = tableNum(DimAttributeCustTable); //Initialize the map to store the backing entity types dimAttrIdx = new Map(Types::Integer, Types::Integer); //Get the record Id (dimension set id) for current ledger to find active dimensions dimensionSetId = DimensionCache::getDimensionAttributeSetForLedger(); //Find all the active dimensions for current ledger except main account and store there //backing entity type in the map while select * from dimAttr order by Name where dimAttr.Type != DimensionAttributeType::MainAccount join RecId from dimAttrSetItem where dimAttrSetItem.DimensionAttribute == dimAttr.RecId && dimAttrSetItem.DimensionAttributeSet == dimensionSetId { dimAttrCount++; dimAttrIdx.insert(dimAttr.BackingEntityType, dimAttrCount); info(dimAttr.Name); } //initialize hash key array to null for (i = 1; i<= dimAttrCount; i++) valueKeyHashArray[i] = emptyGuid(); //Find the Dimension attribute record for the dimension to work on dimAttr.clear(); select firstonly dimAttr where dimAttr.BackingEntityType == custBackEntityType; //Get the backing entity type for the dimension value to process select firstOnly dimAttrCustTable where dimAttrCustTable.Value == '1101'; //Find the required Dimension Attribute Value record //Create if necessary dimAttrValue = DimensionAttributeValue::findByDimensionAttributeAndEntityInst(dimAttr.RecId, dimAttrCustTable.RecId, false, true); //Store the required combination hash keys valueKeyHashArray[dimAttrIdx.lookup(custBackEntityType)] = dimAttrValue.HashKey; //Calculate the hash for the current values hash = DimensionAttributeValueSetStorage::getHashFromArray(valueKeyHashArray, dimAttrCount); //Null hash indicates no values exist, which may occur if the user entered an invalid value for one dimension attribute if (hash == conNull()) { throw error("Wrong value for Customer Dimension"); } // Search for existing value set dimAttrValueSet = DimensionAttributeValueSet::findByHash(hash); // This value set does not exist, so it must be persisted if (!dimAttrValueSet) { ttsbegin; // Insert the value set with appropriate hash dimAttrValueSet.Hash = hash; dimAttrValueSet.insert(); //Insert Customer dimension set item dimAttrValueSetItem.clear(); dimAttrValueSetItem.DimensionAttributeValueSet = dimAttrValueSet.RecId; dimAttrValueSetItem.DimensionAttributeValue = dimAttrValue.RecId; dimAttrValueSetItem.DisplayValue = dimAttrCustTable.Value; dimAttrValueSetItem.insert(); ttscommit; } //Update the customer default dimension field ttsBegin; select forUpdate custTable where custTable.AccountNum == '1101'; custTable.DefaultDimension = dimAttrValueSet.RecId; custTable.Update(); ttsCommit; info(strFmt("%1", dimAttrValueSet.RecId)); }
上面代码参考http://sumitsaxfactor.wordpress.com/2011/12/28/defaulting-financial-dimensions-ax-2012/,设置客户代码为“1101”客户的“Customer”维度为其自身。
代码更改默认维度还有其他一些方法,在以后的文章中再讨论。