Once you activate the BDEF and generate the Behavior Implementation (BIL) class, you will see that the class zcl_bp_dh_R_PurCtr has 4 local classes
◉ lhc_Header
◉ lhc_Item
◉ lhc_Account
◉ lsc_ZDH_R_PurCtr
In the create method of class lhc_Header, we
◉ get an instance of class cl_ctr_handler_mm class to interact with outline agreement buffer
◉ set the outline agreement header data from payload
◉ If there are no errors, generate a %PID and map it to %CID and fill mapped-header table
◉ Also buffer the combination of %PID and %CID in a buffer class – in this case zcl_dh_purctr_buffer
This tells RAP that setting header data was successful.
Sample code from create method of class lhc_Header
METHOD create.
DATA:
lt_messages TYPE mepo_t_messages_bapi,
ls_header TYPE outline_agrmnt_header_data.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<ls_header_payload>).
DATA(lv_pid) = lcl_util=>generate_pid( ).
DATA(lo_handler) = lcl_factory=>get_bo_handler_instance(
EXPORTING
iv_pid = lv_pid
iv_mode = cl_mmpur_constants=>hin
IMPORTING
et_messages = lt_messages
).
IF lo_handler IS BOUND.
ls_header-data = CORRESPONDING #( <ls_header_payload>-%data MAPPING FROM ENTITY ).
ls_header-datax = CORRESPONDING #( <ls_header_payload> MAPPING FROM ENTITY USING CONTROL ).
lo_handler->set_outl_agreement_header( is_outl_agrmnt_header = ls_header
is_outl_agrmnt_set_flags = VALUE #( header = abap_true ) ).
lo_handler->outl_agrmnt_process( IMPORTING ex_messages = lt_messages ).
ENDIF.
IF NOT line_exists( lt_messages[ msgty = 'E' ] ).
INSERT VALUE #( %cid = <ls_header_payload>-%cid
%pid = lv_pid ) INTO TABLE mapped-header.
zcl_dh_purctr_buffer=>get_instance( )->add_header( VALUE #( cid = <ls_header_payload>-%cid
pid = lv_pid ) ).
ELSE.
"
" Create failed. Fill FAILED and REPORTED
"
ENDIF.
ENDLOOP.
ENDMETHOD.
NOTE: I have added the complete listing of all utility classes such as lcl_util, lcl_fctory, zcl_dh_purctr_buffer as attachments to this blog.
Perform similar set of operations in CBA_Item method of class lhc_Header . Important things to note here
◉ get the same instance of cl_ctr_handler_mm class. In this case, this is a singleton class. However, it is important to not try to call open again when trying to set item data into outline agreement buffer. This is handled in lcl_factory class
◉ Generate a new %PID for each successfully created item instance and map it to their corresponding %CID.
◉ Also buffer this mapping for future use during save sequence
Coding from method CBA_Item looks like this
METHOD cba_Item.
DATA:
lv_ctr TYPE ebeln,
lt_messages TYPE mepo_t_messages_bapi,
lt_item TYPE outline_agrmnt_t_item.
LOOP AT entities_cba ASSIGNING FIELD-SYMBOL(<ls_item_cba>).
LOOP AT <ls_item_cba>-%target ASSIGNING FIELD-SYMBOL(<ls_item_payload>).
IF <ls_item_cba>-PurchaseContract IS NOT INITIAL.
lv_ctr = <ls_item_cba>-PurchaseContract.
ELSEIF <ls_item_cba>-%cid_ref IS NOT INITIAL.
DATA(ls_header_key) = zcl_dh_purctr_buffer=>get_instance( )->get_header_by_cid( iv_cid = <ls_item_cba>-%cid_ref ).
ELSE.
"-- Invalid parent key
ENDIF.
DATA(lo_handler) = lcl_factory=>get_bo_handler_instance(
EXPORTING
iv_ctr_number = lv_ctr
iv_pid = ls_header_key-pid
iv_mode = cl_mmpur_constants=>hin
IMPORTING
et_messages = lt_messages
).
IF lo_handler IS BOUND.
lt_item = VALUE #( ( id = lo_handler->get_id( )
data = CORRESPONDING #( <ls_item_payload>-%data MAPPING FROM ENTITY )
datax = CORRESPONDING #( <ls_item_payload> MAPPING FROM ENTITY USING CONTROL ) ) ).
lo_handler->set_outl_agrrement_items( it_items = lt_item
is_item_set_flags = VALUE #( item = abap_true ) ).
lo_handler->outl_agrmnt_process( IMPORTING ex_messages = lt_messages ).
ENDIF.
IF NOT line_exists( lt_messages[ msgty = 'E' ] ).
DATA(lv_item_pid) = lcl_util=>generate_pid( ).
INSERT VALUE #( %cid = <ls_item_payload>-%cid
%pid = lv_item_pid ) INTO TABLE mapped-item.
zcl_dh_purctr_buffer=>get_instance( )->add_item( VALUE #( cid = <ls_item_payload>-%cid
cid_ref = <ls_item_cba>-%cid_ref
pid = lv_item_pid ) ).
ELSE.
"
" Create failed. Fill FAILED and REPORTED
"
ENDIF.
CLEAR: lt_item, lv_ctr, lv_item_pid, ls_header_key.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
Save Phase
In case of late numbering main task in save phase is to map the document number that is generated to %PIDs. This needs to be done in adjust_numbers step. Also, in late numberingscenarios, save step can usually be empty.
Here, we call post method of cl_ctr_handler_mm which will send back a success message with Purchase contract number if all went well. Then, we read all buffered mappings of %CID and %PID for all entities, and map the Purchase Contract number accordingly. This is done in method _map_results of lsc_ZDH_R_PurCtr here:
METHOD adjust_numbers.
mo_buffer = zcl_dh_purctr_buffer=>get_instance( ).
mt_header_buffer = mo_buffer->get_all_header_data( ).
mt_item_buffer = mo_buffer->get_all_item_data( ).
LOOP AT lcl_factory=>get_all_handlers( ) INTO DATA(ls_bo_handler).
ls_bo_handler-handler->outl_agrmnt_post(
EXPORTING
im_no_commit = abap_true
IMPORTING
ex_messages = DATA(lt_messages)
).
ASSIGN lt_messages[ msgty = 'S' msgid = '06' msgno = '017' ] TO FIELD-SYMBOL(<ls_message>).
IF sy-subrc = 0.
DATA(lv_ctr_created) = <ls_message>-ebeln.
_map_results(
EXPORTING
iv_header_pid = ls_bo_handler-root_pid
iv_ctr = lv_ctr_created
CHANGING
cs_mapped = mapped
).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD _map_results.
ASSIGN mt_header_buffer[ pid = iv_header_pid ] TO FIELD-SYMBOL(<ls_header_buff>).
IF <ls_header_buff> IS ASSIGNED.
cs_mapped-header = VALUE #( BASE cs_mapped-header ( %pid = iv_header_pid
PurchaseContract = iv_ctr ) ).
LOOP AT mt_item_buffer ASSIGNING FIELD-SYMBOL(<ls_item_buff>) USING KEY sorted_cid_ref WHERE cid_ref = <ls_header_buff>-cid.
cs_mapped-item = VALUE #( BASE cs_mapped-item ( %pid = iv_header_pid
PurchaseContract = iv_ctr
PurchaseContractItem = <ls_item_buff>-key-PurchaseContractItem ) ).
ENDLOOP.
ENDIF.
ENDMETHOD.
EML Example
Start the interaction phase and set header and item data with below EML. I am using some test data here. Adjust them according to your setup:
MODIFY ENTITIES OF ZDH_R_PurCtr
ENTITY Header
CREATE SET FIELDS WITH VALUE #( ( %cid = 'header1'
CompanyCode = '0001'
PurchasingDocumentCategory = 'K'
PurchaseContractType = 'MK'
PurchasingOrganization = '0001'
PurchasingGroup = '001'
DocumentCurrency = 'EUR'
Supplier = 'STANDARD'
ValidityStartDate = sy-datum
ValidityEndDate = sy-datum + 30
QuotationSubmissionDate = sy-datum ) )
CREATE BY \_Item
SET FIELDS WITH VALUE #( ( %cid_ref = 'header1'
%target = VALUE #( ( %cid = 'item1'
CompanyCode = '0001'
PurchasingDocumentItemCategory = '0'
Material = 'AD-08'
ManufacturerMaterial = 'AD-08'
PurchaseContractItemText = 'Integration test PASS API'
MaterialGroup = '01'
Plant = '0001'
StorageLocation = '0001'
ContractNetPriceAmount = '1000'
TargetQuantity = '200'
NetPriceQuantity = '1'
OrderPriceUnit = 'EA'
OrderQuantityUnit = 'EA'
AccountAssignmentCategory = ''
MultipleAcctAssgmtDistribution = '' " = Single, 1 = By Qty, 2 = By %, 3 = By Amount
OrdPriceUnitToOrderUnitDnmntr = '1'
OrderPriceUnitToOrderUnitNmrtr = '1'
GoodsReceiptIsExpected = 'X'
GoodsReceiptIsNonValuated = ''
EvaldRcptSettlmtIsAllowed = ''
InvoiceIsExpected = 'X'
InvoiceIsGoodsReceiptBased = 'X'
PurgDocPriceDate ='99991231' ) ) ) )
FAILED DATA(failed)
REPORTED DATA(reported)
MAPPED DATA(mapped).
Note, after this, if everything went well, then mapped-header and mapped-item will contain the respective %PID . Now, it is important to convert this to Purchase Contract number. For this, RAP provides a new syntax CONVERT KEY OF ... So, the COMMIT ENTITIES... looks like this now:
This is possible because of the mapping done in adjust_numbers method of lsc_zdh_r_PurCtr class
COMMIT ENTITIES
BEGIN RESPONSE OF ZDH_R_PurCtr
FAILED DATA(failed_late)
REPORTED DATA(reported_late).
LOOP AT mapped-header ASSIGNING FIELD-SYMBOL(<mapped>).
CONVERT KEY OF ZDH_R_PurCtr FROM <mapped>-%pid TO DATA(ls_ctr).
<mapped>-PurchaseContract = ls_ctr-PurchaseContract.
ENDLOOP.
COMMIT ENTITIES END.
Looking into debugger…
we find mapped filled with %PID after interaction phase and with Purchase Contract number CONVERT KEY OF...
No comments:
Post a Comment