Enterprise Resource Planning Blogs by SAP
Get insights and updates about cloud ERP and RISE with SAP, SAP S/4HANA and SAP S/4HANA Cloud, and more enterprise management capabilities with SAP blog posts.
cancel
Showing results for 
Search instead for 
Did you mean: 
Hongjun_Qian
Product and Topic Expert
Product and Topic Expert
It's heard several times that customer prefers having the splitting result for some dimensions in accounting side (table ACDOCA) and in Cash Flows (table FQM_FLOW). However, Flow Builder, including Flow Builder 1.0 and Flow Builder Plus (a.k.a. Flow Builder 2.0) are building flows from original operation documents, (entries in table BSEG), hence Flow Builder cannot consume the splitting result in ACDOCA.

Within this post, I provided a step-by-step tutorial to add customer logic by leveraging the standard EXIT of Flow Builder plus to achieve the goal. As it is a step-by-step tutorial, this post covers only:

  • Profit center. This post focuses on 'Profit Center' dimension only.

  • Amount splitting support only one currency: transaction currency.

  • Discount is not considered at all.


 

Step 1. Create a BAdI Implementation for Flow Builder Plus


Flow Builder Plus used the central BAdI of One Exposure to adjust the final flow: BADI_FQM_FLOW_ADJUST_CORE.



The BAdI filter ORIGIN_APPLICATION shall be set to ‘BSEGV’.

 

Step 2.  BAdI Implementation Logic


The kernel BAdI implementation logic is,

  • Read out Journal Entry Line Item per document line item.

  • Re-splitting flows based on the Journal Entry Line item with the given dimensions. Within this document, the specified dimension is Profit Center.


 

Read out Journal Entry Line Item


The parameter CT_FLOWS which passes to BAdI interface with structure FQMS_FLOW_CORE_LINE_IDX.


Among all fields, the following fields are the key of accounting document:

  • Company Code

  • FI Fiscal year

  • FI Document

  • FI Document Line Item


So, read out the Journal Entry Line Item:
SELECT CompanyCode, FiscalYear, AccountingDocument, AccountingDocumentItem, ProfitCenter, AmountInTransactionCurrency
from I_GLAccountLineItemRawData WITH PRIVILEGED ACCESS
where SourceLedger = @lv_rldnr
and CompanyCode = @ls_grp-company_code
and FiscalYear = @ls_grp-fi_fiscal_year
and AccountingDocument = @ls_grp-fi_document_number
and AccountingDocumentItem = @ls_grp-fi_document_line_item
into table @lt_acdoca.

 

The reading logic shall only focus on the leading ledger. The following code will fetch out the leading ledger in use.
CALL FUNCTION 'FAGL_GET_LEADING_LEDGER'
IMPORTING
e_rldnr = lv_rldnr.

 

Re-split the amount


After reading out the Journal Entry Line Item into internal table `lt_acdoca`, now we need re-split the flows in internal table `ct_flows`.

Here comes the sample codes which distribute the amount among the flows:
LOOP AT lt_acdoca ASSIGNING FIELD-SYMBOL(<fs_acdoca>) WHERE ProfitCenter IS NOT INITIAL.
data(lv_amt) = <fs_acdoca>-AmountInTransactionCurrency.
CLEAR: lb_entryfound.

WHILE lv_amt <> 0.
LOOP AT lt_flows ASSIGNING <fs_flow> WHERE profit_center is INITIAL.
lb_entryfound = abap_true. " Avoid endless loop.

IF <fs_flow>-amount > lv_amt.
" Flow splitting
<fs_flow>-profit_center = <fs_acdoca>-ProfitCenter.
DATA(lv_remain) = <fs_flow>-amount - lv_amt.
<fs_flow>-amount = lv_amt.
APPEND value #( line_number = <fs_flow>-line_number profit_center = <fs_acdoca>-ProfitCenter ) TO lt_changedflow.

" New flow
CLEAR ls_newflow.
ADD 1 TO lv_max_linenumber.
ls_newflow = <fs_flow>.
ls_newflow-line_number = lv_max_linenumber.
ls_newflow-amount = lv_remain.
CLEAR: ls_newflow-profit_center.
APPEND ls_newflow TO lt_flows.
APPEND ls_newflow TO lt_newflows.

CLEAR: lv_amt. " Stop the loop
ELSE.
<fs_flow>-profit_center = <fs_acdoca>-ProfitCenter.
lv_amt = lv_amt - <fs_flow>-amount.

APPEND value #( line_number = <fs_flow>-line_number profit_center = <fs_acdoca>-ProfitCenter ) TO lt_changedflow.
ENDIF.

IF lv_amt EQ 0. EXIT. ENDIF.
ENDLOOP.

IF lb_entryfound IS INITIAL. EXIT. ENDIF.
ENDWHILE.
ENDLOOP.
ENDLOOP.

 

Merge into output result


After the splitting, the result need be merged back.
LOOP AT lt_changedflow ASSIGNING FIELD-SYMBOL(<fs_changedflow>).
LOOP AT ct_flows ASSIGNING <fs_flow> WHERE line_number = <fs_changedflow>-line_number.
<fs_flow>-profit_center = <fs_changedflow>-profit_center.
ENDLOOP.
ENDLOOP.

 

Appendix


Attached the full code snippet (for the method) as plain text.
  METHOD if_fqm_flow_enhancements_core~adjust_flows.

**********************************************************************
* Consume the result in ACDOCA for Profit center
**********************************************************************

" Leading ledger
DATA lv_rldnr TYPE rldnr.

CALL FUNCTION 'FAGL_GET_LEADING_LEDGER'
IMPORTING
e_rldnr = lv_rldnr.

data lt_flows type FQMT_FLOW_CORE_LINE_IDX.
data: begin of ls_changedflow,
line_number type int4,
profit_center type prctr,
end of ls_changedflow.
data lt_changedflow like table of ls_changedflow.
data lv_max_linenumber type int4.
DATA ls_newflow type fqms_FLOW_CORE_LINE_IDX.
data lt_newflows type fqmt_FLOW_CORE_LINE_IDX.
DATA lb_entryfound type boolean.
data: begin of ls_acdoca,
CompanyCode type bukrs,
FiscalYear type gjahr,
AccountingDocument type belnr_d,
AccountingDocumentItem type buzei,
ProfitCenter type prctr,
AmountInTransactionCurrency type FINS_VWCUR12,
end of ls_acdoca.
data lt_acdoca like table of ls_acdoca.

LOOP AT ct_flows ASSIGNING FIELD-SYMBOL(<fs_flow>).
IF lv_max_linenumber < <fs_flow>-line_number.
lv_max_linenumber = <fs_flow>-line_number.
ENDIF.
ENDLOOP.

LOOP AT ct_flows ASSIGNING FIELD-SYMBOL(<wa>)
GROUP BY ( company_code = <wa>-company_code fi_fiscal_year = <wa>-fi_fiscal_year
fi_document_number = <wa>-fi_document_number fi_document_line_item = <wa>-fi_document_line_item )
INTO data(ls_grp).

" Read the ACDOCA out
CLEAR: lt_acdoca.
TEST-SEAM acdoca_read.
SELECT CompanyCode, FiscalYear, AccountingDocument, AccountingDocumentItem, ProfitCenter, AmountInTransactionCurrency
from I_GLAccountLineItemRawData WITH PRIVILEGED ACCESS
where SourceLedger = @lv_rldnr
and CompanyCode = @ls_grp-company_code
and FiscalYear = @ls_grp-fi_fiscal_year
and AccountingDocument = @ls_grp-fi_document_number
and AccountingDocumentItem = @ls_grp-fi_document_line_item
into table @lt_acdoca.
END-TEST-SEAM.

clear lt_flows.
LOOP AT GROUP ls_grp INTO DATA(ls_grp_flow).
CLEAR ls_grp_flow-profit_center.
APPEND ls_grp_flow TO lt_flows.
ENDLOOP.

" Merge flows: lt_flows and ACDOCA
SORT lt_flows BY amount.
SORT lt_acdoca BY AmountInTransactionCurrency.

LOOP AT lt_acdoca ASSIGNING FIELD-SYMBOL(<fs_acdoca>) WHERE ProfitCenter IS NOT INITIAL.
data(lv_amt) = <fs_acdoca>-AmountInTransactionCurrency.
CLEAR: lb_entryfound.

WHILE lv_amt <> 0.
LOOP AT lt_flows ASSIGNING <fs_flow> WHERE profit_center is INITIAL.
lb_entryfound = abap_true. " Avoid endless loop.

IF <fs_flow>-amount > lv_amt.
" Flow splitting
<fs_flow>-profit_center = <fs_acdoca>-ProfitCenter.
DATA(lv_remain) = <fs_flow>-amount - lv_amt.
<fs_flow>-amount = lv_amt.
APPEND value #( line_number = <fs_flow>-line_number profit_center = <fs_acdoca>-ProfitCenter ) TO lt_changedflow.

" New flow
CLEAR ls_newflow.
ADD 1 TO lv_max_linenumber.
ls_newflow = <fs_flow>.
ls_newflow-line_number = lv_max_linenumber.
ls_newflow-amount = lv_remain.
CLEAR: ls_newflow-profit_center.
APPEND ls_newflow TO lt_flows.
APPEND ls_newflow TO lt_newflows.

CLEAR: lv_amt. " Stop the loop
ELSE.
<fs_flow>-profit_center = <fs_acdoca>-ProfitCenter.
lv_amt = lv_amt - <fs_flow>-amount.

APPEND value #( line_number = <fs_flow>-line_number profit_center = <fs_acdoca>-ProfitCenter ) TO lt_changedflow.
ENDIF.

IF lv_amt EQ 0.
EXIT.
ENDIF.
ENDLOOP.

IF lb_entryfound IS INITIAL.
EXIT.
ENDIF.
ENDWHILE.
ENDLOOP.
ENDLOOP.

IF lt_newflows IS NOT INITIAL.
APPEND LINES OF lt_newflows TO ct_flows.
CLEAR: lt_newflows.
ENDIF.

" Reflect the updates into the changed table.
LOOP AT lt_changedflow ASSIGNING FIELD-SYMBOL(<fs_changedflow>).
LOOP AT ct_flows ASSIGNING <fs_flow> WHERE line_number = <fs_changedflow>-line_number.
<fs_flow>-profit_center = <fs_changedflow>-profit_center.
ENDLOOP.
ENDLOOP.
ENDMETHOD.