ACDOCA vs BSEG vs FAGLFLEXT

关于统一日记账ACDOCA你必须知道的事

统一日记账(Universal Journal)是S/4HANA在财务领域最大的创新。它把原先分散的SAP财务模块数据,整合到了一个完全集成的后台表中,就是Table ACDOCA。

下图就展示了ACDOCA是如何将总账(General Ledger),利润中心会计(Profit Center Accounting),固定资产会计(Fixed Asset Accounting),物料账(Material Ledger),成本(Controlling),获利分析(Profitability Analysis)等各个财务子模块的数据集成到一起的。

这样一个集成的信息源,就能生成各式各样的报表:固定资产,库存,应收应付,利润,销售成本COGS),资产负债表,损益表等等。它也让以前ECC系统中的很多后台索引表(Index)和汇总表(Total)变得不再需要。

在本文中,我将就一些关键点,跟ECC的数据结构做一个比较。

1. ACDOCA里有的,BSEG里不一定有

以下的一些凭证行项目,都是只在ACDOCA表里面存在,而在BSEG表里不存在的(你可以通过BKPF表的BSTAT字段的凭证状态U来识别):

  • 资产折旧过账

  • 特定账套(Ledger)过账

  • 外币评估过账

  • CO内部凭证

2. 年末结转数字存储在ACDOCA的Period 000中

ACDOCA把上一年度的结转数放在Period 000中,这样便于计算YTD(year-to-date)数字,你不需要回去找上一年度末的数字。

3. ACDOCA的体量比BSEG大很多

ACDOCA表中的行项目数量可能会非常大,因为评分拆分,所有的行项目都被拆分到了最小的维度,再考虑到多个账套的存在,凭证行项目数量还要翻倍。

所以,从长期业务运行的角度,数据库大小和磁盘大小都需要提前考虑好。

4. 已归档的数据会在BKPF/BSEG中被删除,但在ACDOCA中依然存在

当你在财务模块中做数据归档时,对应数据会被从BKPF/BSEG表中删除。

然而,在ACDOCA表中,数据不会立刻被删除,而是添加一条反向的凭证到ACDOCA表里,让汇总余额为0。

要实际上删除ACDOCA中的数据,必须要执行Compression Run。

Compression Run是一个数据压缩的过程,它用汇总数据来替代明细数据。它的数据颗粒度就跟年末余额结转的颗粒度一致,对于余额不产生影响。

5. 对于同样的维度,BSEG和ACDOCA可能有差异

对于同一条记录的同一个字段,你可能会发现在BSEG和ACDOCA中的值可能会不一样。

例如,你可以在Entry View上,通过替代(Substitution)来修改Assignment字段(ZUONR)的值,但是它不一定会被拷贝到ACDOCA表里面。拷贝到ACDOCA是由BAdI BADI_FINS_ACDOC_BSEG_FIELDS控制的,所以当你在系统中做替代时,需要关注一下。

6. Coding Block中的自定义字段 - 集成到ACDOCA

当你在Coding Block中添加自定义字段的时候,自定义字段也会被增加到ACDOCA中。

但是,在各种凭证输入的场景中,这些自定义字段是如何被使用的,将取决于具体的定义。你在Table FINSC_ACDOC_FCT中,能看到这些自定义字段的各种属性。例如,自定义字段在以下各种流程的使用都是可以具体定义的:

  • 在损益类科目的年末结转中

  • 在资产负债类科目的年末结转中

  • 在科目余额中

  • 在科目报表中

  • 在科目余额评估时

  • 在对FI凭证做修改时

  • 在科目分摊时

  • 在汇总层级定义时

7. 很多时候,报表的数据需求会超越ACDOCA所能提供的信息

有时候报表不仅仅是关于财务细节的,它可能会混合其他维度,例如主数据中的字段,供应商名称,成本中心层次等。

所以,在报表设计时,你需要考虑使用SAP预建的一些CDS view,它们已经混合了ACDOCA的数据和其他维度的数据。并且对于新报表来说,应该尽量基于ACDOCA做开发,而不是BSEG。

其它

更精确的理解ACDOCA,应该意识到其是一个存储实际财务凭证(Actuals)的表,对于noted item(例如down payment request预付款请求凭证),并不会更新到ACDOCA中,而是仍然存储在BSEG中。

请见下例 (F-47创建一笔预付款请求)-

原因

对于注释项目noted item,其属于标记的项目,并不会产生直接的财务影响。

ACDOCA用于用于最终财务表报的出具,而BSEG仍然会存在并用于相关应收/应付(AP/R)流程凭证的记录,例如清账,付款,催款,预付款请求等操作。

在上例中,预付款请求凭证不会更新到ACDOCA中,但如果对于这个预付款请求发生的真实的付款动作,那么这个真实的付款凭证则会被更新至ACDOCA中。

更简单的理解,可以认为一笔真实的财务凭证,一定是有借有贷的。

小结

统一日记账ACDOCA整合了财务模型,但BSEG仍然会用于相关财务流程中数据的存储,对于Item级别的凭证数据,应当结合ACDOCA和BSEG查看数据。

但在ACDOCA中并没有这个FI凭证的记录 -

S/4 HANA中的ACDOCT和FAGLFLEXT

S/4 HANA中的ACDOCT和FAGLFLEXT - 氢氦 - 博客园 (cnblogs.com)

最近的几个需求让我对ACDOCT和FAGLFLEXT这两个财务相关表(准确地说是视图)产生了一些了解,同时也发现某些开发同行和业务顾问并没有认识到这些东西。因此我打算从技术角度来说明一下这两个视图在S4中的实际面貌。当然因为我并不了解FICO方面的任何业务知识,所以也只是进行技术角度的说明。

本文内容基于 S/4 1709版本;某些内容可能和其他版本不是完全符合,特别是具体的DDL代码部分。

财务报表开发中经常会出现有关期初余额和本期发生额的需求,传统上获取期初余额的方式是从FAGLFLEXT或ACDOCT中获取结转余额(HSLVT),再加上各期发生额(HSL01, HSL02....)。

比如要获取公司1000的2018年3月的期初余额,ABAP代码的写法是:

SELECTSUM( ( hslvt + hsl01 + hsl02 ) ) FROM faglflext WHERE rbukrs = '1000'AND ryear = '2018'INTO @DATA(l_balance).

这只是段简单的示例代码,实际需求中可能要按科目等条件取出各个期间分组汇总。并且,为了适应动态的查询条件,通常要使用Field Symbol,在内表中对数据进行累加操作,颇为繁琐。

那么,HSLVT和HSL01, HSL02....等数据是从哪里来的呢?如果把FAGLFLEXT和ACDOCT视为数据库表,读者可能会认为,它们是通过某些结转操作,由系统汇总计算后得来并存储到数据库中的。但实际上,FAGLFLEXT和ACDOCT都只是视图,而非透明表。可以理解成,它们当中的数据不是数据库中既有的,而是和各种报表程序一样、是对其它表的数据进行实时处理后临时生成的结果。

打开SE11可以看到:

可以看到,它们实际上是ABAP CDS视图。如果不了解ABAP CDS视图的话,可以暂时把它理解成使用SQL语言建立的数据模型,通过使用注解,还能为它赋予其它能力。

推荐通过Eclipse来查看CDS视图的定义,具体操作方式不提。

CDS视图中的数据通常是从透明表中取得的,这里以FAGLFLEXT为例:

观察视图的DDL源,寻找其中的FROM关键字:

可以发现这个视图结合了2个源。其一是FAGLFLEXT_BCK,查询可知这是旧数据的备份表;另一个是FGL_FAGLFLEXT,

打开FGL_FAGLFLEXT,发现它还是个CDS视图(因为完整定义过长,只截取了部分代码,下同):

可以看到,FGL_FAGLFLEXT中的HSLVT和HSL01, HSL02字段,是对FGL_GLTT2中相应字段的汇总得来的。对应语句:sum(hslvt) as hslvt。

打开FGL_GLTT2,会发现该视图中的金额汇总自FGL_GLTT1,所以这里就不贴FGL_GLTT2的定义了,直接看FGL_GLTT1:

@AbapCatalog.sqlViewName: 'FGLV_GLTT1'@AccessControl.authorizationCheck: #NOT_REQUIRED

@ObjectModel.usageType.serviceQuality: #X

@ObjectModel.usageType.sizeCategory: #XL

@ObjectModel.usageType.dataClass: #MIXED

@EndUserText.label: 'G/L totals: create the period block'

define view FGL_GLTT1 asselectfrom FGL_GLTT0

{

rclnt,

ryear,

0as objnr00,

0as objnr01,

0as objnr02,

0as objnr03,

0as objnr04,

0as objnr05,

0as objnr06,

0as objnr07,

0as objnr08,

drcrk,

case poper

when'000'then'016'elsecast( lpad( cast ( 16* (1+ div( cast(poper as abap.int4) -1, 16) ) as abap.char(12) ), 3, '0') as abap.numc(3))

endas rpmax,

activ, rmvct, rtcur,

runit, awtyp, rldnr, rrcty, rvers, logsys, racct, cost_elem, rbukrs,

rcntr, prctr, rfarea, rbusa, kokrs, segment,

scntr, pprctr, sfarea, sbusa, rassc, psegment,

//<$VF>

fikrs, rfund, rgrant_nbr, rbudget_pd, sfund, sgrant_nbr, sbudget_pd,

re_bukrs, re_account, vname, egrup, recid,

//<$FIELDS>//<$VF>

………………

………………

case poper when'000'then hsl else0endas hslvt,

case mod( cast(poper as abap.int4 ), 16) when1then hsl else0endas hsl01,

case mod( cast(poper as abap.int4 ), 16) when2then hsl else0endas hsl02,

case mod( cast(poper as abap.int4 ), 16) when3then hsl else0endas hsl03,

case mod( cast(poper as abap.int4 ), 16) when4then hsl else0endas hsl04,

case mod( cast(poper as abap.int4 ), 16) when5then hsl else0endas hsl05,

case mod( cast(poper as abap.int4 ), 16) when6then hsl else0endas hsl06,

case mod( cast(poper as abap.int4 ), 16) when7then hsl else0endas hsl07,

case mod( cast(poper as abap.int4 ), 16) when8then hsl else0endas hsl08,

case mod( cast(poper as abap.int4 ), 16) when9then hsl else0endas hsl09,

case mod( cast(poper as abap.int4 ), 16) when10then hsl else0endas hsl10,

case mod( cast(poper as abap.int4 ), 16) when11then hsl else0endas hsl11,

case mod( cast(poper as abap.int4 ), 16) when12then hsl else0endas hsl12,

case mod( cast(poper as abap.int4 ), 16) when13then hsl else0endas hsl13,

case mod( cast(poper as abap.int4 ), 16) when14then hsl else0endas hsl14,

case mod( cast(poper as abap.int4 ), 16) when15then hsl else0endas hsl15,

case mod( cast(poper as abap.int4 ), 16)

when0thencase poper

when'000'then0else hsl

endelse0endas hsl16,

………………

………………

timestamp

}

可以清楚地看到,原来结转余额HSLVT其实就是期间POPER = 000时的金额,HSL01,HSL02就是期间POPER = 001,002时的金额....

对应语句是:case poper when '000' then hsl else 0 end as hslvt,,和case mod( cast(poper as abap.int4 ), 16) when 1 then hsl else 0 end as hsl01

继续找下去可以得知FGL_GLTT1的数据来自于表ACDOCA(Universal Journal Entry Line Items)。也就是说,每次从FAGLFLEXT中查询数据,实际上相当于经过了FGL_GLSI_ACD->FGL_GLSI_ACD->FGL_GLTT1->FGL_GLTT2->FGL_FAGLFLEXT->V_FAGLFLEXT_DDL一系列中间层逻辑处理,其实际的数据源则是表ACDOCA。当然这些视图中可能还包含其它细节..

以上是对FAGLFLEXT的分析,ACDOCT也是差不多的,具体的条件有点差别。

FAGLFLEXT和ACDOCT的存在体现了CDS所具备的强大能力。不过,毕竟它们只是兼容视图,又包含这样多的中间层...按照一般的原则,程序中的中间层越多,性能就越差。因此,在了解到它们中的数据的实际来源后,也许在某些情况下,直接从ACDOCA中通过聚合函数获取期初余额之类的东西会有更好的性能。

按这样的思路改写文初获取1000公司在2018年3月的期初余额的代码,可以写成:

SELECTSUM( hsl ) FROM acdoca WHERE rbukrs = '1000'AND gjahr = '2018'AND poper < '003'INTO @DATA(l_balance).

是不是简单了很多呢?

最后,再次重申,本文只是从技术角度介绍下我对ACDOCT,FAGLFLEXT的了解。在实际业务中,这两个视图中的数据可能和分类账、凭证状态之类的东西有关...其中的数据与ACDOCA中的汇总数据并不一定在任何情况下都完全相等。

示例代码:

从ACDOCA中获取公司代码1000,分类账0L,科目1122020000的期初余额、本期发生额、期末余额、本年累计发生额:

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值