Skip to Content
Technical Articles
Author's profile photo Thomas Peters

IFRS16: Migration of Foreign Currency Assets

Introduction

A couple of days ago a customer came up with the following question:

Having all data in either SAP ERP Financials or SAP Contract and Lease Management on our SAP ERP system, the question is, how to transfer foreign currency leasing contracts from our old SAP ERP system having no foreign currency depreciation area to our new SAP S/4HANA system. And, in addition to that, how can we reconcile the migrated figures?

My initial idea was, why not use the valuation cashflow and transform it, so it looks like data that is coming from the standard SAP ERP database tables where fixed asset data is stored?

At first sight I thought this should be a no-brainer since all data is recorded somewhere and all what is left to do is some data transformation. However, as often things are different if you start having a closer look…

Assumption

From my experience the basis of any migration approach for fixed assets in SAP ERP is the relevant content of the according database tables, i.e. ANLC, ANEK, ANEP etc. To keep things simple, I solemnly focus on the aspect of leased assets and how to get the data out of the system, in a format that is alike to how data is recorded in the above mentioned database tables.

Since I want to focus on the principle of the data transformation I assume that there is only one depreciation area that needs to be considered.

Since there is no real-time integration between the cash flow in SAP Contract and Lease Management and the fixed assets in SAP ERP data, migrated figures might be not comparable and the possibility of retro-active changes in SAP Contract and Lease Management can make things even worse. On the other hand, the cash flow in SAP Contract and Lease Management is the best we have when it comes to foreign currency figures that are not posted in SAP ERP as part of fixed asset accounting.

In other words, what I present here is not a 100% solution but it is better than just using fixed asset data and performing a foreign currency migration on a defined key date.

Approach

Having a closer at the cashflow data from SAP Contract and Lease Management that generated in a valuation run it shows that despite of the deviating format nearly all necessary information is available to obtain an output similar to what is recorded e.g. in the tables ANLC, ANLP and ANEP in SAP ERP.

All cashflow items are recorded in database table VICECFPROCESS. However, it is much more convenient to use the function module API_RE_CE_GET_CASHFLOW to obtain the cashflow, since setting parameter IF_CFNEWEST to ‘X’ allows us to get the latest valid cashflow for a specific contract.

Having a closer look at the cashflow the relevant information for fixed assets,

  • APC changes and
  • depreciation,

could easily be identified using the transaction type from SAP Contract and Lease Management. However, the cashflow type, i.e. field CFTYPE, already classifies items as acquisition, i.e. CFTYPE 1, and depreciation, i.e. CFTYPE 2. Having a closer look to both acquisition items also include impairments whereas depreciation only include normal depreciation. The split between real acquisitions and impairments is also easily by using the reference flow type relation, i.e. REFFLOWREL.

Now, that all information is available to transform the cashflow into the structure of both tables ANLP and ANLC, we are set to perform a year-end data migration. To perform a mid-year migration, however, transactional values, i.e. ANEP records, are still to be generated in the required format.

Starting from the cash flow, the goal is to find the original transaction and enrich the according data.

The tricky part about the transactional data is the asset transaction type since in the cashflow we only have the according transaction type from the SAP Contract and Lease Management. Technical there are two options, either go through the logic that is processed when documents are posted in daily business, or try to identify the asset document. Since customizing is likely to change I decided to take the latter approach.

The steps are:

  1. Once an accounting document has been created for a valuation cashflow item from database table VICECFRULE
  2. the according identifier is recorded in this very item and
  3. the linked record in database table VIRADOCITEM can be identified.
  4. Using the reference document number from the header record from database table VIRADOC
  5. the corresponding record in database table ANEK can be looked up and
  6. finally the line item in ANEP with the asset transaction type is identified.

Solution

The import parameters are the company code, the fiscal year – normally the fiscal year of the migration -, the valuation rule and the pseudo-depreciaton area, that is used for the output, in combination with the requested currency.

For productive use the currency will be one where there is no according depreciation area in place, since this is what the whole function module is designed for. For testing purpose, however, I also used the function module in test-mode with the local currency. In this case the exported data should match with what is recorded in the database tables ANLC and ANEP.

So far I was able to test the functionality of the following code in only a few systems, so there might be some glitches left. Especially the impairment has not yet been well tested due to missing data. Beside adaptions on the migration programs are required on your side.

function Z_REFX_GET_ASSET_VALUES.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_BUKRS) TYPE  BUKRS
*"     REFERENCE(IV_GJAHR) TYPE  GJAHR OPTIONAL
*"     REFERENCE(IV_CERULE) TYPE  RECECERULE
*"     REFERENCE(IV_AFABE) TYPE  AFABE_D DEFAULT '99'
*"     REFERENCE(IV_WAERS) TYPE  WAERS
*"  EXPORTING
*"     REFERENCE(ET_ANLC) TYPE  FAA_T_ANLC
*"     REFERENCE(ET_ANLP) TYPE  AA_T_ANLP
*"     REFERENCE(ET_ANEP) TYPE  FAA_T_ANEP
*"  EXCEPTIONS
*"      UNKNOWN_TRANSACTION
*"----------------------------------------------------------------------

  data: LT_INTRENO       type RE_T_INTRENO,
        LT_CE_CASHFLOW   type BAPI_RE_T_CE_CASHFLOW_INT,
        LS_ANLC          type ANLC,
        LS_ANLP          type ANLP,
        LS_ANEP          type ANEP,
        LV_ASSETOBJ      type RECEASOBJNR,
        LV_DEPPOST       type D,
        LV_DETAILVALIDTO type RECADETAILVALIDTO,
        LV_ANBTR         type ANBTR.

  clear: ET_ANLC, ET_ANLP, ET_ANEP.

*
* get relevant contracts
*
  concatenate `AN` IV_BUKRS into LV_ASSETOBJ.

  LV_ASSETOBJ+6(1) = '%'.

* after the latest update the currency is recorded in the cash flow items
  select distinct INTRENO
    from VICERULE
   where ASSETOBJNR like @LV_ASSETOBJ
     and RULECURR eq @IV_WAERS
  union 
* old valuation runs may have the currency not available in the cash flow
  select distinct VICNCN~INTRENO
    from VICERULE
         inner join VICNCN
      on VICERULE~INTRENO eq VICNCN~INTRENO
   where VICERULE~ASSETOBJNR like @LV_ASSETOBJ
     and VICERULE~RULECURR eq ''
     and VICNCN~RECNCNCURR eq @IV_WAERS
   order by INTRENO
    into table @LT_INTRENO.

* any contract found
  check sy-dbcnt gt 0.

* get date of last depreciation run
  select AFBLGJ, AFBLPE up to 1 rows
    from TABA
    into @data(LS_TABA)
   where BUKRS eq @IV_BUKRS
   order by AFBLGJ descending, AFBLPE descending.

  endselect.

  concatenate LS_TABA-AFBLGJ LS_TABA-AFBLPE+1(2) '01' into LV_DEPPOST.

  LV_DEPPOST = CL_RECA_DATE=>SET_TO_END_OF_MONTH( LV_DEPPOST ).

* get highest open year for asset postings
  select single T093C~LGJAHR
    from T093C
   where BUKRS eq @IV_BUKRS
    into @data(LV_LGJAHR).

  if SY-SUBRC eq 0.
    LV_DETAILVALIDTO(4) = LV_LGJAHR.
    LV_DETAILVALIDTO+4(4) = '1231'.
  else.
* if not defined select all available values
    LV_DETAILVALIDTO = RECA0_DATE-MAX.
  endif.

*
* loop through all relevant contracts
*
  loop at LT_INTRENO into data(LV_INTRENO).

    call function 'API_RE_CE_GET_CASHFLOW'
      exporting
*       ID_BUKRS          =
*       ID_RECNNR         =
        ID_INTRENO        = LV_INTRENO
*       IO_OBJECT         =
*       ID_DETAIL_DATA_FROM       =
*       ID_DETAIL_DATA_TO =
*       ID_TERMNO         =
        ID_CERULE         = IV_CERULE
*       ID_CFTYPE         =
*       ID_CFSTATUS       =
*       IF_CFNEWEST       = ABAP_TRUE
      importing
        ET_CE_CASHFLOW    = LT_CE_CASHFLOW
      exceptions
        ERROR             = 1
        others            = 2.

    if SY-SUBRC ne 0.
      continue.
    endif.

* collect values for each year.
    loop at LT_CE_CASHFLOW assigning field-symbol(<LS_CE_CASHFLOW>)
      where ASSETOBJNR cp 'AN*'.

      LS_ANLC = value #( BUKRS = <LS_CE_CASHFLOW>-ASSETOBJNR+2(4)
                         ANLN1 = <LS_CE_CASHFLOW>-ASSETOBJNR+6(12)
                         ANLN2 = <LS_CE_CASHFLOW>-ASSETOBJNR+18(4) ).

* use identifier for the pseudeo 'depreciation area' from import parameter
      LS_ANLC-AFABE = IV_AFABE.

      LS_ANLC-GJAHR = cond #( when <LS_CE_CASHFLOW>-POSTINGDATE is initial
                              then <LS_CE_CASHFLOW>-DFAELL(4)
                              else <LS_CE_CASHFLOW>-POSTINGDATE(4) ).

      LV_ANBTR = cond #( when CL_RECDC_FLOW_TYPE=>GET_DETAIL( ID_FLOWTYPE = <LS_CE_CASHFLOW>-BOOK_FLOWTYPE )-SSOLHAB eq 'S'
                         then - <LS_CE_CASHFLOW>-BBWHR
                         else <LS_CE_CASHFLOW>-BBWHR ).

      case <LS_CE_CASHFLOW>-CFTYPE.

        when RECE2_CFTYPE-ACQUISITION.
          if <LS_CE_CASHFLOW>-REFFLOWREL eq RECE3_REFFLOWREL-UNPLANNED_DEPRECIATION or 
             <LS_CE_CASHFLOW>-REFFLOWREL eq RECE3_REFFLOWREL-UNPLANNED_APPRECIATION.
* Impairment
            LS_ANLP = corresponding #( LS_ANLC ).
            LS_ANLP-AFABER = LS_ANLC-AFABE.
            LS_ANLP-PERAF = <LS_CE_CASHFLOW>-DFAELL+4(2).

            LS_ANLP-AAFAP = LV_ANBTR.
            LS_ANLC-AAFAP = LV_ANBTR.
            if <LS_CE_CASHFLOW>-DFAELL le LV_DEPPOST.
              LS_ANLP-AAFAG = LS_ANLP-AAFAP.
              LS_ANLC-AAFAG = LS_ANLC-AAFAP.
            endif.
  
            collect LS_ANLP into ET_ANLP. " collect periodic value changes

          else.
* APC change
            LS_ANLC-ANSWL = LV_ANBTR.
          endif.

* Only transactions in the current are of any interest
          if IV_GJAHR is initial or
             IV_GJAHR eq <LS_CE_CASHFLOW>-DFAELL(4).

            LS_ANEP = corresponding #( LS_ANLC ).
            LS_ANEP-BZDAT = <LS_CE_CASHFLOW>-DFAELL.
            LS_ANEP-ANBTR = LV_ANBTR.

* get original asset transaction type
            select single ANEP~LNRAN, ANEP~BELNR, ANEP~BUZEI, ANEP~BZDAT, ANEP~BWASL
              from ANEP inner join ANEK
                on ANEP~BUKRS eq ANEK~BUKRS
               and ANEP~ANLN1 eq ANEK~ANLN1
               and ANEP~ANLN2 eq ANEK~ANLN2
               and ANEP~LNRAN eq ANEK~LNRAN
                   inner join VIRADOC
                on VIRADOC~PROCESSID eq ANEK~XBLNR
                   inner join VIRADOCITEM
                on VIRADOC~DOCGUID eq VIRADOCITEM~DOCGUID
                   inner join TIVCERULECC
                on TIVCERULECC~BUKRS eq ANEP~BUKRS
               and TIVCERULECC~DEPRAREA eq ANEP~AFABE
             where VIRADOCITEM~REFGUID eq @<LS_CE_CASHFLOW>-CFGUID
               and ANEP~BUKRS eq @LS_ANLC-BUKRS
               and ANEP~ANLN1 eq @LS_ANLC-ANLN1
               and ANEP~ANLN2 eq @LS_ANLC-ANLN2
               and VIRADOCITEM~OBJNR eq @<LS_CE_CASHFLOW>-ASSETOBJNR
               and TIVCERULECC~CERULE eq @IV_CERULE
              into ( @LS_ANEP-LNRAN, @LS_ANEP-BELNR, @LS_ANEP-BUZEI, @LS_ANEP-BZDAT, @LS_ANEP-BWASL ).

* skip if no transaction type was found
            if SY-SUBRC ne 0.
              CONTINUE.
            endif.

            append LS_ANEP to ET_ANEP.
          endif.

        when RECE2_CFTYPE-DEPRECIATION.
* Ordinary Depreciation
          LS_ANLP = corresponding #( LS_ANLC ).
          LS_ANLP-AFABER = LS_ANLC-AFABE.
          LS_ANLP-PERAF = <LS_CE_CASHFLOW>-DFAELL+4(2).

          LS_ANLP-NAFAP = 
          LS_ANLC-NAFAP = - LV_ANBTR.

          if <LS_CE_CASHFLOW>-DFAELL le LV_DEPPOST.
            LS_ANLP-NAFAG = LS_ANLP-NAFAP.
            LS_ANLC-NAFAG = LS_ANLC-NAFAP.
          endif.

          collect LS_ANLP into ET_ANLP. " collect periodic value changes

        when others.
* should never happen
          raise UNKNOWN_TRANSACTION.
      endcase.

      collect LS_ANLC into ET_ANLC. " collect value changes

    endloop.

  endloop.

* ensure values are properly sorted for the periodic summarization
  sort ET_ANLP by BUKRS ANLN1 ANLN2 AFABER GJAHR PERAF.

* calculate periodic values
  loop at ET_ANLP into LS_ANLP.

    loop at ET_ANLP assigning field-symbol(<LS_ANLP>)
      where BUKRS eq LS_ANLP-BUKRS
        and ANLN1 eq LS_ANLP-ANLN1
        and ANLN2 eq LS_ANLP-ANLN2
        and AFABER eq LS_ANLP-AFABER
        and GJAHR eq LS_ANLP-GJAHR.

      if <LS_ANLP>-PERAF gt LS_ANLP-PERAF.
        add LS_ANLP-NAFAZ to -NAFAG.
      endif.
      add LS_ANLP-NAFAZ to <LS_ANLP>-NAFAP.
    endloop.

  endloop.

* calculate cumulated values
  loop at ET_ANLC into LS_ANLC.

    loop at ET_ANLC assigning field-symbol(<LS_ANLC>)
      where BUKRS eq LS_ANLC-BUKRS
        and ANLN1 eq LS_ANLC-ANLN1
        and ANLN2 eq LS_ANLC-ANLN2
        and AFABE eq LS_ANLC-AFABE
        and GJAHR gt LS_ANLC-GJAHR.

      add LS_ANLC-ANSWL to <LS_ANLC>-KANSW.
      add LS_ANLC-NAFAP to <LS_ANLC>-KNAFA.
      add LS_ANLC-AAFAP to <LS_ANLC>-KAAFA.

    endloop.

  endloop.

* restrict values to selected fiscal year
  if IV_GJAHR is not initial.
    delete ET_ANLC where GJAHR ne IV_GJAHR.
  endif.

  sort: ET_ANLC, ET_ANLP, ET_ANEP.

endfunction.

Conclusion

So, what do we get calling the above function module?

What we have to think of is how in general in fixed asset accounting transactional figures are migrated, i.e. extracting data from the database tables ANLC, ANLP and ANEP. All what there is to do is to call the above function module using correct import parameters, i.e. the company code, the fiscal year of the migrated figures, the name of the valuation rule, e.g. IFRS16, a currency – likely that of the controlling area, and a deprecation area that must not be part of the chart of depreciation.

The output is three tables, i.e. ANLC, ANLP and ANEP, that just needs to be merged to database extract of theses tables. Focusing on the existing migration programs the existing workaround to generated foreign currency values must be omitted for all fixed assets where there is data available from SAP Contract and Lease Management.

Since the assumption was to only have one depreciation area we are done and the migration does respect both,

  • local currency values that are – as before – extracted from the database tables ANLC, ANLP, ANEP, and some others, and
  • foreign currency values that – if available – are coming from the SAP Contract and Lease Management, or – as before – are determined elsewise.

I’m curious about your experience in the migration of foreign currency leasing contracts.

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.