关于Dynamics AX2009的加权平均算法
本文讨论Dynamics AX2009的版本为RU7,Application版本号为5.0.1500.4570.
由于对财务知识的匮乏,本文权当抛砖引玉,期望得到精通财务的AX专业人士的指点,共同找出应用Dynamics AX2009的加权平均算法的合理方式。
本文分为两个部分
第一部分是测试用例,使用Dynamics AX2009 RU7进行加权平均算法的测试。
第二部分为代码分析。
测试用例
由于国内一般都会包含已收货或者已发货但是未开票的物料成本,所以本文的测试用例使用的物料包含物理库存,使用加权平均法进行库存关帐。
库存成本的计价方法以及是否包含实际成本,是在库存模型组设置的,且AX的逻辑是月中使用移动平均价,月底按照库存模型设置的计价方式进行重算,这个基本逻辑从AX最初的版本就是这样的,接触过AX的人都知道,所以本文不再赘述。
为了把精力集中在加权平均算法的讨论上,对于如何设置维度组来设定成本的核算粒度,比如是以仓库为单位还是以库位为单位或者以批次为单位进行核算,本文不再赘述,假设该物料关联的维度组以仓库为单位进行成本核算,并且所有的出入库的仓库都是同一个仓库。
为了便于问题的描述,本文以最简单的采购和销售业务为例进行测试用例的设计。
物料关联的库存模型组的设置如下图所示:
1.对物料做两笔采购,其中一笔数量为1,价格为10,一笔数量为1,价格为20,只过账装箱单,不开发票
过账装箱单后产生的库存交易记录如下所示:
由于没有过账发票,所以成本额没有金额,过账了装箱单,实际成本额分别为10和20,这个没问题。
这时候做销售出库,不开盘,由于包含了实际成本,所以这时出库的成本应为(10+20)/2 * 1 = 15.
销售订单如下:
过账装箱单,产生的库存交易记录如下:
结果符合预期。
如果现在做库存的关帐,体现不出是否调整了,因为如果按照加权平均的逻辑,这时候做库存关帐,出库成本也是(10*1+20*1)/(1+1) * 1= 15,之前移动平均算出来的成本也是15,所以即便Dynamics AX 2009 RU7的关帐逻辑进行了调整,到目前为止的用例也没办法判断的,因为到目前为止还不需要进行成本调整。
为了体现成本的变化情况,再做一笔数量为1,采购价为30的采购订单,并做装箱单,不开发票,如下图所示:
过账产生的库存交易记录如下:
这时再做销售出库,不开发票,这时的移动平均价为22.50,所以销售出库的成本为22.50
过账装箱单产生的库存交易记录如下:
到目前为止该物料的所有的库存交易记录如下:
物料的加权平均价应为 (10*1+20*1+30*1)/(1+1+1) = 20
按照正常的逻辑,两笔出库的成本应该都被调整为20。
做库存关帐动作,完成后再次查看该物料的库存交易记录。
从结果看,是没有进行任何调整的。
因为库存模型组里选择了包含实际库存,但是在库存关帐的时候从结果上看并没有进行任何调整,看上去是没有考虑未开票的交易记录。
下面继续进行测试,如果只把采购订单过账发票,会不会调整?采购订单过账发票后的交易记录如下图所示。
三笔采购的记录都已经开发票,由于开票时并没有更改金额,所以成本额与实际成本额一致,销售记录保持不变。
这时进行库存关帐,关帐后查看物料的库存交易记录。
从结果看,没有进行任何调整。
继续测试用例,将第一笔销售订单过账发票,结果如下,第一笔销售订单的成本额为18.75,这个值的算法也很简单(10*1+20*1+30*1-22.50*1)/(1+1+1-1) = 18.75.
这时进行库存关帐,调整结果如下:
从结果可以看出,只有已开票的销售记录发生了调整,成本额调整成了加权平均的值,已发货但未开票的销售记录并未发生调整。
注意产生的2012年9月30日的两条记录,状态是已采购和已售出,这个是为了提高加权平均计价方式算法的效率,如果本月的入库记录超过一条,那么就会合并生成一条已采购的记录,同时为了库存金额和数量的正确,生成一条相反的状态为已售出的记录。
注意已售出的记录总是完全结算的,这条记录对应的是已经开票的入库记录,这些已经开票的入库记录也是完全结算的。而加权平均库存结转的状态为已采购的这条记录的结算数量为1,还有2个未结算,因为这条记录对应的是出库记录的结算,而销售订单状态为已售出的物料只有1个。
从上面的过程可以得出两个结论:
1.加权平均算法只会结转已开票额记录,只有已经开票的入库和出库记录才会参与加权平均算法的计算。
2.结算时如果有多笔入库记录,会先将所有的未全部结算且已经开票的入库记录合并成生成两条加权平均库存结转的记录,状态分别为已采购和已售出,已售出的这条记录的状态为已结算,将已开票的未结算的入库记录的状态变成已结算,然后用状态为已采购的这条记录去结算出库记录。
代码分析
从InventCostItemDim类的Load方法中可以看出,对于加权平均和加权平均日期这两种计价方式,AX确实不会考虑已收(发)货未开票的记录的。
InventDim inventDim;
InventDimParm inventDimParm;
StatusReceipt statusReceipt = StatusReceipt::Purchased;
StatusIssue statusIssue = StatusIssue::Sold;
boolean physicalDateCriteria;
;
if (this.inventModelGroup(inventCostList.ItemId).InclPhysicalValueInCost)
{
if (this.inventModelGroup(inventCostList.ItemId).InventModel != InventModel::AverageCost &&
this.inventModelGroup(inventCostList.ItemId).InventModel != InventModel::AverageCostDate)
{
statusReceipt = StatusReceipt::Received;
statusIssue = StatusIssue::Deducted;
physicalDateCriteria = true;
}
}
至于加权平均算法的计算过程,可以查看方法updateModelAverage ,这个方法的逻辑比较简单,这里就不再分析了。
结论
从整个分析的过程来看,Dynamics AX2009 RU7的加权平均算法是不考虑已收(发)货未开票的交易记录的,也就是暂估部分的交易记录是不予考虑的,从我的理解看这个在国内是没办法用的,因为国内大部分企业都是有暂估的,极端情况下,如果某个月的入库和出库都不开票,月底库存关帐就没作用了,整个计价方式变成移动平均而不是加权平均了。
【推荐】中国电信天翼云云端翼购节,2核2G云服务器一口价38元/年
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步