A couple of days ago a customer came up with the following question:
Having all data either in SAP ERP Financials or in SAP Contract and Lease Management on our SAP ERP system, how can we transfer foreign currency leasing contracts from our old SAP ERP system where there is no foreign currency depreciation area into our new SAP S/4HANA system? And how can we reconcile the migrated figures?
My initial idea was, why not use the valuation cash flow 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 feasible since all data is recorded somewhere and all what is left to do is some data transformation.
To keep things simple I’m assuming that there is only one depreciation area that needs to be considered. So there is only one identifier for the faked depreciation area that is part of the importing parameters of the code below.
Since there is no real-time integration between SAP Contract and Lease Management cash flow and the link 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.
Having a closer at the cash flow 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 and ANEP in SAP ERP.
All cash flow 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 cash flow, since setting parameter IF_CFNEWEST to ‘X’ allows us to obtain the latest valid cash flow for a specific contract.
Having a closer look at the cash flow the relevant information for fixed assets, i.e.
- APC changes and
can easily be identified using the transaction type from SAP Contract and Lease Management. In detail only the cash flow records are of interest, where the field CFTYPE is 1 or 2.The first ones identify transactions posted to an asset directly whereas the second identifies the periodic value adjustments, i.e. ordinary depreciation.
Now that all information is available to transform the cash flow into the structure of table ANLC, we are set to to perform a year-end data migration. To perform a mid-year migration, however, transactional values are still to be generated in the required format.
The goal is to find the original transaction and enrich the according document with the data form the cash flow.
The tricky part about the transactional data is the asset transaction type since in the cash flow from SAP Contract and Lease Management we only have the according transaction type. What’s more, we also need the original document, since the goal is to extend the originally posted finance document by the foreign currency recorded as a cash flow item in SAP Contract and Lease Management.
Once an accounting document has been created for a valuation cash flow item from database table VIRADOCITEM the according identifier is recorded in this very item and the linked record in database table VIRADOCITEM can be identified. Using the reference document number from the header record from database table VIRADOC the corresponding record in database table ANEK can be looked up and finally the line item in ANEP with the asset transaction type is identified.
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. 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_WAERS) TYPE WAERS *" REFERENCE(IV_AFABE) TYPE AFABE_D DEFAULT '99' *" EXPORTING *" REFERENCE(ET_ANLC) TYPE FAA_T_ANLC *" 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_ANEP type ANEP, LV_ASSETOBJ type RECEASOBJNR, LV_DEPPOST type D, LV_DETAILVALIDTO type RECADETAILVALIDTO, LV_ANBTR type ANBTR. clear: ET_ANLC, 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 max( AFBLGJ ) as AFBLGJ, max( AFBLPE ) as AFBLPE from TABA into @data(LS_TABA) where BUKRS eq @IV_BUKRS. 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 'CE8' or <LS_CE_CASHFLOW>-REFFLOWREL eq 'CE9'. * Impairment LS_ANLC-AAFAP = LV_ANBTR. if <LS_CE_CASHFLOW>-DFAELL le LV_DEPPOST. LS_ANLC-AAFAG = LS_ANLC-AAFAP. endif. 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_ANLC-NAFAP = - LV_ANBTR. if <LS_CE_CASHFLOW>-DFAELL le LV_DEPPOST. LS_ANLC-NAFAG = LS_ANLC-NAFAP. endif. when others. * should never happen raise UNKNOWN_TRANSACTION. endcase. collect LS_ANLC into ET_ANLC. endloop. endloop. * calculate cummulated 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_ANEP. endfunction.
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 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 two tables, i.e. ANLC 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, 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.