ODATA DRAFT SCENARIOS
What is Draft?
A draft is the state of the business object when its data is not persisted in the actual tables but is stored in some temporary tables which can be quickly retrieved to continue working (from the place left) in case the work is left in the middle due to some reason. Draft Management Process Flow:
Consider an application with Sales Order (SO) Header and Item data. The data can be displayed and updated or new SOs can be created.
Drafts play no role in Display functionality. It is when any user either enters into an update mode or a create mode drafts are involved.
A Draft can be:
Implement Draft Management:
Create Draft tables to store the data temporarily. In this case, draft tables will be require for Header and Item data.
Tables for draft data:
Steps to create Entity types:
Go to SAP Gateway Service Builder(SEGW).
Click on create project node.
Provide the project name, description, package name and click on Continue.
Select the Data model and Right click on data model.
Select Import and click on DDIC Structures node.
Provide the entity name and DDIC table name which table you want to import.
Click on Next.
Select the required fields which you want to display/perform operations.
Click on Next.
Select the atleast one key fields from that structure and click on finish.
Create one more entity type for Item details.
Click on Save.
Click on Generate Runtime Objects node.
By default/Implicitly 4 classes, one technical model and one technical service is created.
Click on continue.
In addition to this one more entity with just a text field is defined to be used as the return type
Create one return type structure.
Add one return type.
Steps to create Association :
Right click on Data model.
Select Create and click on Association node.
Provide the Association name, Principle name as Header entity name, Dependent name as Item entity name and provide the cardinality for displaying the item details and provide the navigation property name.
Click on Next.
Provide dependent property name as common field name for both header and item entity.
Click on next.
Click on Finish.
Create one deep structure in MPC_EXT class.
Provide Navigation property name for item details like as shown in below
Steps to create Function Import:
3 function imports, CreateDraft, DeleteDraft, and SaveOrder are created to achieve the functionality. All use the Return Type as the entity type Return.
Right click on Data model.
Select the create and Click on Function import.
Provide the Function import name, Click on continue.
Provide the return type kind as Entity type, Return type as Return entity name, pass the cardinality and select the HTTP method as post.
Like this create 2 more function import for DeleteDraft, and SaveOrder.
Provide the parameter for function import.
Code Reference from ZCL_ZGR_ODATA_DRAFT_SC_DPC_EXT
Read and Query Operations:
These operations usually will refer to the actual tables/Standard BAPI etc., to get data.
method SO_HEADERSET_GET_ENTITY.
DATA : lv_vbeln TYPE vbak-vbeln.
DATA(it_keys) = io_tech_request_context->get_keys( ).
lv_vbeln = VALUE #( it_keys[ name = 'VBELN' ]-value optional ).
lv_vbeln = |{ lv_vbeln ALPHA = IN }|.
select SINGLE FROM vbak
FIELDS vbeln,
erdat,
erzet,
ernam,
netwr,
waerk,
vkorg,
vtweg,
spart,
kunnr
WHERE vbeln = _vbeln
INTO CORRESPONDING FIELDS OF _entity.
endmethod.
method SO_HEADERSET_GET_ENTITYSET.
SELECT FROM vbak
FIELDS vbeln, erdat, erzet, ernam, netwr,
waerk, vkorg, vtweg, spart, kunnr
INTO CORRESPONDING FIELDS OF TABLE _entityset
UP TO 20 ROWS.
endmethod.
Read/ Get Item data:
method SO_ITEMSET_GET_ENTITY.
DATA ls_keys TYPE zcl_zgr_odata_draft_sc_mpc=>ts_so_item.
io_tech_request_context->get_converted_keys(
IMPORTING
es_key_values = ls_keys " Entity Key Values - converted
).
SELECT SINGLE FROM vbap
FIELDS vbeln, posnr, matnr, arktx, zmeng, meins,
netwr, waerk, werks, lgort, vstel, route
WHERE vbeln = _keys-vbeln
AND posnr = _keys-posnr
INTO CORRESPONDING FIELDS OF _entity.
endmethod.
METHOD so_itemset_get_entityset.
DATA lv_vbeln TYPE vbak-vbeln.
IF io_tech_request_context->get_source_entity_type_name( ) = 'SO_Header'.
DATA(It_Keys) = io_tech_request_context->get_source_keys( ).
lv_vbeln = VALUE #( it_keys[ name = 'Vbeln' ]-value OPTIONAL ).
lv_vbeln = |{ lv_vbeln ALPHA = IN }|.
SELECT FROM vbap
FIELDS vbeln, posnr, matnr, arktx, zmeng, meins,
netwr, waerk, werks, lgort, vstel, route
WHERE vbeln = _vbeln
INTO CORRESPONDING FIELDS OF TABLE _entityset.
ELSE.
SELECT FROM vbap
FIELDS vbeln, posnr, matnr, arktx, zmeng, meins,
netwr, waerk, werks, lgort, vstel, route
INTO CORRESPONDING FIELDS OF TABLE _entityset.
ENDIF.
ENDMETHOD.
CREATE_DRAFT Method:
An additional method is created in the DPC_EXT class with importing parameter VBELN i.e., Order Number and Exporting parameter Return which is the same type as extra entity.
This method will check weather the draft exists for the order. If it does and it is by another user, it will return an error text. Otherwise, the method will copy the data from the standard table to custom draft tables ZGR_T_SOH_DRAFT and ZGR_T_SOI_DRAFT.
To Keep the logic simple, the method uses incremental logic to generate a key. In an actual scenario, we will either use a hash generator or number range to create the draft key.
Note: Create_Draft method is a custom method which is have importing and Returning parameter.
method CREATE_DRAFT.
"Check if draft exists
SELECT SINGLE FROM zgr_t_soh_draft
FIELDS *
INTO (ls_draft).
IF sy-subrc EQ 0. "Draft exist
IF sy-uname = ls_draft-ernam. "Draft by same user
RETURN = VALUE zgr_s_return( test = 'S Draft success' ).
ELSE.
RETURN-test = |E Draft user : { ls_draft-ernam }|.
ENDIF.
ELSE. "No Draft
SELECT SINGLE FROM vbak
FIELDS vbeln, erdat, erzet, ernam, netwr,
waerk, vkorg, vtweg, spart, kunnr
WHERE vbeln = @vbeln
INTO (ls_vbak).
IF sy-subrc EQ 0.
ls_draft = CORRESPONDING #( ls_vbak ).
ls_draft-ernam = sy-uname.
INSERT zgr_t_soh_draft FROM ls_draft.
IF sy-subrc EQ 0.
RETURN-test = 'S Draft Success'.
ELSE.
RETURN-test = 'S Draft Failed'.
ENDIF.
ENDIF.
"Add items to the draft
SELECT FROM vbap
FIELDS mandt, vbeln, posnr, matnr, arktx, zmeng, meins,
netwr, waerk, werks, lgort, vstel, route
WHERE vbeln = @vbeln
INTO TABLE (lt_items).
IF sy-subrc EQ 0.
INSERT zgr_t_soi_draft FROM TABLE _items.
ENDIF.
ENDIF.
endmethod.
CREATE Operation:
Create Operation should be called only for item data. For header data instead of create, created draft should be called. Item create operation, actually only creates an entry in the draft table.
method SO_ITEMSET_CREATE_ENTITY.
DATA: ls_Final TYPE zcl_zgr_odata_draft_sc_mpc_ext=>TY_FINAL,
ls_item type zcl_zgr_odata_draft_sc_mpc=>ts_so_item.
io_data_provider->read_entry_data(
IMPORTING
es_data = ls_final
).
ls_item = CORRESPONDING #( ls_final ).
INSERT zgr_t_soi_draft FROM ls_item.
IF Sy-subrc EQ 0.
er_entity = ls_item.
ENDIF.
endmethod.
UPDATE Operation:
Update operation for header and item entities will update the draft tables.
Update Operation For Header Data:
method SO_HEADERSET_UPDATE_ENTITY.
DATA: ls_final TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ty_final,
ls_header TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ts_so_header.
io_data_provider->read_entry_data(
IMPORTING
es_data = ls_final
).
ls_header = CORRESPONDING #( ls_final ).
IF sy-subrc Eq 0.
MODIFY zgr_t_soh_draft FROM ls_header.
er_entity = ls_header.
ENDIF.
endmethod.
Update operation for Item data:
method SO_ITEMSET_UPDATE_ENTITY.
DATA: ls_final TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ty_final,
ls_item TYPE zcl_zgr_odata_draft_sc_mpc_ext=>ts_so_item.
io_data_provider->read_entry_data(
IMPORTING
es_data = ls_final
).
ls_item = CORRESPONDING #( ls_final ).
IF sy-subrc EQ 0.
MODIFY zgr_t_soi_draft FROM ls_item.
ENDIF.
endmethod.
DELETE Operation:
In this case, a delete operation is not implemented as a Sales Order can not be deleted from the system. Usually, it will be set as all items rejected etc., which can be done in an update operation.
Function Import Implementation:
Method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION is redefined to implement the function imports.
CreateDraft:
DeleteDraft:
SaveOrder:
Function Import implementation:
METHOD /iwbep/if_mgw_appl_srv_runtime~execute_action.
DATA : lv_vbeln_out TYPE vbeln.
DATA : ls_header_in TYPE bapisdhd1,
lt_items_in TYPE STANDARD TABLE OF bapisditm,
lt_partners TYPE STANDARD TABLE OF bapiparnr,
lt_return TYPE STANDARD TABLE OF bapiret2.
CASE iv_action_name.
WHEN 'CreateDraft'.
TRY.
DATA(lt_pars) = io_tech_request_context->get_parameters( ).
DATA(lv_vbeln) = VALUE vbeln_va( lt_pars[ name = 'SALESORDER' ]-value OPTIONAL ).
lv_vbeln = |{ lv_vbeln ALPHA = IN }|.
DATA(ls_return) = create_draft( vbeln = lv_vbeln ).
CATCH cx_sy_itab_line_not_found.
"Error
ls_return-test = 'E Invalid call'.
ENDTRY.
copy_data_to_ref(
EXPORTING
is_data = ls_return
CHANGING
cr_data = er_data
).
WHEN 'DeleteDraft'.
TRY.
lt_pars = io_tech_request_context->get_parameters( ).
lv_vbeln = VALUE vbeln_va( lt_pars[ name = 'SALESORDER' ]-value ).
lv_vbeln = |{ lv_vbeln ALPHA = IN }|.
DELETE FROM zgr_t_soh_draft WHERE vbeln = _vbeln.
IF sy-subrc EQ 0.
DELETE FROM zgr_t_soi_draft WHERE vbeln = _vbeln.
ls_return-test = 'S draft deleted'.
ENDIF.
CATCH cx_sy_itab_line_not_found.
"Error
ls_return-test = 'E Invalid call'.
ENDTRY.
copy_data_to_ref(
EXPORTING
is_data = ls_return
CHANGING
cr_data = er_data
).
WHEN 'SaveOrder'.
TRY.
lt_pars = io_tech_request_context->get_parameters( ).
lv_vbeln = VALUE vbeln_va( lt_pars[ name = 'SALESORDER' ]-value OPTIONAL ).
lv_vbeln = |{ lv_vbeln ALPHA = IN }|.
select SINGLE vbeln FROM vbak into (lv_vbeln_Test)
WHERE vbeln = _vbeln.
IF sy-subrc NE 0.
CLEAR lv_vbeln_test.
ENDIF.
SELECT SINGLE FROM zgr_t_soh_draft
FIELDS *
WHERE vbeln = _vbeln
INTO (ls_header).
IF sy-subrc NE 0.
ls_return-test = 'E Sales order not found'.
ELSE.
"Fetch draft items
SELECT FROM zgr_t_soi_draft
FIELDS *
WHERE vbeln = _vbeln
INTO TABLE (lt_item).
IF lv_vbeln_test IS NOT INITIAL. "Change mode
DATA : ls_headerx_in TYPE bapisdh1x,
ls_uheader_in TYPE bapisdhd1,
lt_itemsx_in TYPE STANDARD TABLE OF bapisditmx.
lt_items_in = VALUE #( FOR ls_item IN lt_item
( itm_number = ls_item-posnr
short_text = ls_item-arktx
)
).
lt_itemsx_in = VALUE #( FOR ls_item IN lt_item
( itm_number = ls_item-posnr
updateflag = 'U'
short_text = 'X'
)
).
ls_headerx_in-updateflag = 'U'.
lv_vbeln_out = lv_vbeln_test.
CALL FUNCTION 'BAPI_SALESORDER_CHANGE'
EXPORTING
salesdocument = lv_vbeln_test
order_header_inx = ls_headerx_in
TABLES
return = lt_return
ORDER_ITEM_IN = lt_items_in
ORDER_ITEM_INX = lt_itemsx_in
.
ELSE.
ls_header_in-doc_type = 'ZOR1'.
ls_header_in-doc_date = ls_header-erdat.
ls_header_in-created_by = ls_header-ernam.
ls_header_in-currency = ls_header-waerk.
ls_header_in-sales_org = ls_header-vkorg.
ls_header_in-distr_chan = ls_header-vtweg.
ls_header_in-division = ls_header-spart.
lt_partners = VALUE #( ( partn_role = 'AG'
partn_numb = ls_header-kunnr ) ).
lt_items_in = VALUE #( FOR LS_ITEM IN lt_item
( itm_number = ls_item-posnr
material = ls_item-matnr
short_text = ls_item-arktx
target_qty = ls_item-zmeng
target_qu = ls_item-meins
plant = ls_item-werks
store_loc = ls_item-lgort
ship_point = ls_item-vstel
route = ls_item-route
)
).
CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2'
EXPORTING
order_header_in = ls_header_in
IMPORTING
SALESDOCUMENT = lv_vbeln_out
tables
RETURN = lt_return
ORDER_ITEMS_IN = lt_items_in
order_partners = lt_partners
.
ENDIF.
IF NOT line_exists( lt_return[ type = 'E' ] ).
"Update FM to delete the draft
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
* EXPORTING
* WAIT =
* IMPORTING
* RETURN =
.
"Delete Draft
delete FROM zgr_t_soh_draft WHERE vbeln = lv_vbeln.
delete FROM zgr_t_soi_draft WHERE vbeln = lv_vbeln.
ls_return-test = lv_vbeln_out.
ELSE.
ls_return-test = 'E Error in Bapi Call'.
ENDIF.
ENDIF.
CATCH cx_sy_itab_line_not_found.
"Error
ls_return-test = 'E Invalida call'.
ENDTRY.
me->copy_data_to_ref(
EXPORTING
is_data = ls_return
CHANGING
cr_data = er_data
).
ENDCASE.
ENDMETHOD.
Steps to Register the Services:
Goto SAP Gateway services (/IWFND/MAINT_SERVICES).
Click on Add Services node.
Provide the System Alias and Technical service name which is generated while generating the OData services.
Click on Get services node.
Select the services and click on Add Selected Services.
Provide the Package name and click on continue.
Select the services by using Filter.
Click on SAP Gateway Client.
Some basic scenarios output:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.