zoukankan      html  css  js  c++  java
  • D365 FO 科目维度余额计算

    D365 FO提供了一系列的类用来做维度余额的计算。
    凭证的数据存在GeneralJournalAccountEntry和GeneralJournaEntry表里,维度值是表GeneralJournalAccountEntry的LedgerDimension.
    LedgerDimension对应的值在表DimensionAttributeValueCombination里,而具体维度的值又在不同的表里。
    有一些维度组合值是实际业务在生成凭证的时候就使用了,而有一些维度组合是为了分析时用的,比如实际业务发生的过程中,部门,成本中心和利润中心都录入了
    所以凭证GeneralJournalAccountEntry里存的是部门,成本中心和利润中心的组合值,但是需要如果需要按照成本中心和利润中心的组合进行分析,这个值在凭证表里并没有保存。
    为了实现维度组合的计算,AX2012用了财务维度集的概念,定时把GeneralJournalAccountEntry的数据按照中某个维度组合的数据写入到DimensionFocusBalance表里,方便查询任意组合财务维度的值。

    总账->会计科目表->维度->财务维度集

     对于新建的财务维度集要重建余额,也要定期更新余额,要不然最新的凭证记录不在DimensionFocusBalance里,调用系统的类计算维度余额也就查询不到正确的结果了。
    1.使用LedgerBalanceBase查询
    根据某个维度值的组合,查找某个期间的发生额,可以用如下类。

     这里以LedgerBalanceDimAttrValueComboAmounts类为例,查询某个科目在某个利润和成本中心组合下的期间发生额。

    1 LedgerBalanceDimAttrValueComboAmounts       ledgerBalanceDimAttrValueComboAmounts = LedgerBalanceDimAttrValueComboAmounts::construct();
    2         RecId recId = DimensionDynamicAccountResolver::newResolver("51010102-001--007-010").resolve();
    3 
    4         ledgerBalanceDimAttrValueComboAmounts.parmAccountingDateRange(dateStartMth(systemDateGet()), dateEndMth(systemDateGet()));        
    5         ledgerBalanceDimAttrValueComboAmounts.parmIncludeRegularPeriod(true);
    6         ledgerBalanceDimAttrValueComboAmounts.calculateBalance(DimensionAttributeValueCombination::find(recId));
    7         info (num2Str(ledgerBalanceDimAttrValueComboAmounts.getAccountingCurrencyBalance(), 0, 2, 0 ,0));

    如果想查询某个具体的维度组合的值对应的期间发生额,可以用这些类进行查询。
    2.使用试算平衡表
    如果想一次性获取某个财务维度集里包含的所有维度组合的值,通过方法一就显得笨拙了,不可能一个个维度组合起来再一个个查询出来。
    参考试算平衡表的做法。
    路径:总账->查询和报表->试算平衡表
    如果要计算财务维度集ProfitCost某个期间段的金额情况,可以用如下代码:

     1 private LedgerTrialBalanceTmp getMainAccountBalances(
     2                 MainAccountNum       _mainAccountId,
     3                 StartDate           _startDate,
     4                 EndDate             _endDate,
     5                 Name                _dimensionHierarchyName)
     6     {
     7         ttsbegin;
     8 
     9         //更新财务维度集余额
    10         DimensionFocusUpdateBalance::updateBalance(
    11             DimensionHierarchy::findByTypeAndName(DimensionHierarchyType::Focus, 
    12             _dimensionHierarchyName));
    13 
    14         LedgerTrialBalanceTmp trialbalanceTmp;                                                                        
    15         delete_from trialBalanceTmp;
    16 
    17         LedgerTrialBalanceContract trialBalanceContract = new LedgerTrialBalanceContract();
    18         trialBalanceContract.parmFromDate(_startDate);
    19         trialBalanceContract.parmToDate(_endDate);
    20         trialBalanceContract.parmIncludeOpening(true);
    21         trialBalanceContract.parmIncludeClosingAdjustments(false);
    22         trialBalanceContract.parmIncludeClosingTransactions(false);
    23 
    24         //设置过账层
    25         List list = new List(Types::Integer);        
    26         list.addEnd(0);
    27         trialBalanceContract.parmPostingLayers(list);                
    28         trialBalanceContract.parmPrimaryDimensionFocus(_dimensionHierarchyName);
    29         //设置过滤科目        
    30         Map map = new Map(Types::Int64, Types::String);            
    31         map.insert(DimensionAttribute::findByName("MainAccount").RecId, _mainAccountId);
    32         trialBalanceContract.parmDimensionRangeMap(map);
    33         
    34         LedgerTrialBalanceDP trialBalanceDP = new LedgerTrialBalanceDP();
    35         trialBalanceDP.parmDataContract(trialBalanceContract);
    36         trialBalanceDP.setTrialBalanceTmpTable(trialBalanceTmp);
    37 
    38         trialBalanceDP.processReport();
    39         ttscommit;
    40         return trialbalanceTmp;
    41     }

    调用示例

     1  private void callMainAccountBalances()
     2     {
     3         LedgerTrialBalanceTmp trialbalanceTmp = this.getMainAccountBalances(
     4                                 "51010406",
     5                                 dateStartMth(systemDateGet()),
     6                                 dateEndMth(systemDateGet()),
     7                                 "ProfitCost");                                       
     8         while select trialbalanceTmp
     9         {
    10             info(trialbalanceTmp.DimensionValues[1] + " " +
    11                 trialbalanceTmp.DimensionValues[2] + " " +
    12                 trialbalanceTmp.DimensionValues[3] + " " +
    13                 num2Str(trialbalanceTmp.EndingBalance, 0,2, 0 ,0) + 
    14                 num2Str(trialbalanceTmp.AmountDebit, 0,2, 0, 0));
    15         }
    16     }

    D365 FO,目前版本10.0.0.10根据某个维度过滤的代码,感觉有点问题,不知道是微软特意这么设计还是bug。
    比如想按照某个科目过滤,可以用Map把科目传进LedgerTrialBalanceContract,代码在执行的时候是通过表LedgerTransAccountTmp的fillFromDimSetBalWithDimRanges方法取得要过滤的LedgerDimension集合。
    问题在代码的第215行

    r.value(SysQuery::range(_startDate, _endDate));

    这行代码是按照调用方的开始和结束日期来过滤的,问题在于,试算平衡表是要看期初金额的,这样过滤的话,如果调用方输入的期间内,map里指定的科目维度没有发生交易,期初都出不来了。
    不清楚微软fillFromDimSetBalWithDimRanges这个方法设计的初衷,作为调用方来说,我的期望是,如果没传Map进行过滤的时候能返回某个科目维度的记录,那么传了这个科目维度进行过滤的话,也应该能出来。
    不能因为过滤了,就导致不出现这条记录了。
    修改也就简单,扩展一下这个方法,把逻辑改的跟不过滤的逻辑保持一致,把_startDate改成periodStartDate 
    date periodStartDate = LedgerFiscalCalendar::findOpeningStartDateByDate(Ledger::fiscalCalendar(CompanyInfo::current()), _startDate);

  • 相关阅读:
    RPA 产品落地的最后一公里
    H5 native.js 控制wifi
    js 添加css或者链接文件
    js 获取网址中的参数
    js自建readAsBinaryString方法
    js 获取选中文字
    js 身份证校验代码
    js复制对象
    js 字符串编码与解码
    js数组排序
  • 原文地址:https://www.cnblogs.com/Farseer1215/p/12872838.html
Copyright © 2011-2022 走看看