Performing Advanced Extensions

Objective

After completing this lesson, you will be able to perform Advanced Extensions

Explaining an OData Mobile Data Object

An OData mobile data object (also known as OMDO) provides business logic for a business object used in an OData-based mobile application. An OMDO provides both technical implementation and configuration support for the represented business object, including all aspects of related operations such as object creation, update, deletion, or read and downloading. The OMDO also supports configurations such as data distribution rules for data download.

OData requests for a business object are mapped to an OMDO object. The OMDO handler then processes the requests for the OMDO object.

  • For read requests, the OMDO handler considers and enforces the data distribution rules and other configuration settings and determines the proper output response.

  • For create, update, and delete requests, the OMDO handler creates or updates the SAP BusinessObjects in the back-end system as requested in the OData requests, and provides the relevant response.

As mentioned in the Unit-2 of this Training handbook, an ABAP OO class handler is assigned to an OMDO and provides the technical implementation for the OMDO object. The OMDO handler must be a subclass of /MFND/CL_CORE_OMDO_HNDLER_BASE.

The Process Flow of the OMDO determines how the OMDO handler processes OData entity set read requests. Based on the process flow setting, different OMDO handler methods are invoked at runtime. The OMDO handler determines which process flow it supports.

  • Basic Flow without Key List: Typically used by the OMDO handler to support simple SAP BusinessObjects with a single entity type and no change detection support. In general, suitable for SAP Configuration Data.

    Examples of SAP BusinessObjects that use the basic flow without key list include customizing data, such as plant or order type. OMDO handlers that only support basic flow are typically subclasses from /MFND/CL_CORE_OMDO_BASIC_HNDLR.

  • Standard Flow using Key List: Typically used by the OMDO handler to support complex SAP BusinessObjects with multiple entity types, complex relationships between entity types and data distribution rules, and with change detection support. In general, suitable for SAP Master and Transactional Data.

    Examples of SAP BusinessObjects that use the standard flow include transaction data objects such as work orders or notifications; and leading data objects such as equipment or functional locations.

As part of this training, we create:

  • Purchase Organization–Basic Flow

  • Purchase Requisition–Standard Flow

Extend SSAM by Creating a new Entity (Purchase Organization)

Business Scenario

In this exercise, we add a new EntitySet (PurchaseOrganizations) in the backend. This EntitySet is used as a list picker on the client.

You follow these high-level steps for creating a new entity:

Steps to configure an oData Mobile Data Object (oMDO). It includes steps for development, object configuration, model configuration, persona assignment, and testing the service.
  1. Development Tasks (SAP GUI - ABAP Workbench and Dictionary).
    1. Reuse the structure (/SYCLO/MM_PURCHASEORG_STR).
    2. Create oMDO Class Handler for Fetching the Purchase Organizations.
  2. oMDO Object Configuration Tasks (/SYCLO/CONFIGPANEL).

    Assign oMDO Class.

  3. oMDO Model Configuration.
    1. Create Entity & Entity set.
    2. Assign Entity to oMDO Object (create in step 2a).
    3. Configure Associations.
    4. Configure Navigation.
  4. Assign oMDO to Feature and Persona.
    1. Assign oMDO to Feature.
    2. Assign Feature to Persona.
  5. Test using the Gateway Client.
  6. In SAP BAS, perform the Sync Service to update the Metadata.

Note

Use transaction SE24 and there the reference class handler /MERP/CL_MM_PURCHSE_ORG_OD to create your copy Zxxx files. The code snippets provided in this handbook are examples for your reference only. Copy the required coding from the reference class.

Note

The steps below are giving a guide so that you can perform this exercise in your own system landscape.

Task 1: Perform Development Tasks–Create oMDO Class Handler

Steps

  1. Create an oMDO Class for fetching Purchase Order data from SAP with the following data:

    FieldValue
    DescriptionPurchase Organization OMDO Handler for IAM_##
    Instance GenerationPublic
    Usual ABAP ClassSelect the radio button.
    FinalUncheck the checkbox.
    1. Log in to the SAP system and navigate to transaction code SE24.

    2. Enter ZIAM_##_CL_MM_PURCHASE_ORG_OD.

    3. Choose the Create button.

    4. In the pop-up window, choose (the default) Object Type Class radio button.

    5. Choose the Enter button.

    6. Enter the details as given in the table.

    7. Select the Save button.

    8. On the next pop-up window, choose the Local Object button.

  2. Set the super class of this class to /MFND/CL_CORE_OMDO_BASIC_HNDLR.

    1. Once you are in the class, choose the Properties tab.

    2. Choose the Superclass button.

    3. Enter /MFND/CL_CORE_OMDO_BASIC_HNDLR in the superclass name.

    4. Verify that the Final check box is unchecked.

    5. Choose the Save button.

      At this point, you notice that there are few interfaces and method loaded in the corresponding tabs.

      Note

      Set up your environment for better legibility by choosing in the menu bar UtilitiesSettingsClass Builder tab, check the Display Aliases and Group by Interfaces and Superclasses and choose Enter.

  3. Add Object Types.

    Use the following data:

    FieldAttribute1
    TypeGTYP_DOF_FILTER_VALS_STR
    VisibilityPublic
    Typing<keep the initial value> TYPE
    Associated Type 
    DescriptionPurchase Requisition Filters config panel

    1. Choose the Types tab.

    2. Enter the data as given in the preceding tables.

    3. Choose the Direct Type Entry button .

    4. If prompted, choose Save changes.

    5. In the protected sectionenter the following code.

      Code Snippet
      123456789101112
      types: BEGIN OF gtyp_dof_filter_vals_str, purch_org TYPE REF TO /mfnd/core_range_tab, comp_code TYPE REF TO /mfnd/core_range_tab, END OF gtyp_dof_filter_vals_str . data STR_DOF_FILTER_VALS type GTYP_DOF_FILTER_VALS_STR .
    6. Save the changes.

  4. Add two attributes to your class.

    Use the following details for the new Attribute: CONST_PURCHASEORG_ENTITY:

    LevelVisibilityAssociated TypeDescriptionInitial Value
    ConstantPublic/MFND/CORE_TECH_ENTITY_TYP_DTEoMDO - Technical Entity Type'PURCHASEORG'

    Use the following details for the new Attribute: STR_DOF_FILTER_VALS:

    LevelVisibilityAssociated TypeDescriptionInitial Value
    Instance AttributeProtectedGTYP_DOF_FILTER_VALS_STRoMDO–Purchase Org Filter 

    Note

    Single quotes are required for the Initial Value 'PURCHASEORG.'

    1. Choose the Attributes tab.

    2. Enter the values as given in the preceding table.

  5. Redefine the method DEFINE_BO_ENTITY_MODEL with the following code:

    Code Snippet
    1234567
    method /MFND/IF_CORE_OMDO_BO_MODEL~DEFINE_BO_ENTITY_MODEL. CLEAR et_bo_entities. et_bo_entities = VALUE #( ( tech_entity_type = me->const_purchaseorg_entity ref_struct = '/MERP/MM_PURCHASEORG_ENTY_STR' flag_lead_entity = abap_true ) ). endmethod.
    1. Choose the Methods tab.

    2. Choose the find button and search for the method DEFINE_BO_ENTITY_MODEL.

    3. Choose the Redefine button.

    4. Clear the code within the method and copy and paste the given code to the method.

    5. Check syntax (Ctrl + F2).

    6. Choose Save.

  6. Redefine the method GET_DATA_FOR_READ_REQUEST with the following code:

    Code Snippet
    1234567891011121314151617181920212223242526
    method GET_DATA_FOR_READ_REQUEST. DATA: lt_purchaseorg_data TYPE STANDARD TABLE OF /SYCLO/MM_PURCHASEORG_STR. *---Main Section GET REFERENCE OF lt_purchaseorg_data INTO DATA(lref_purchaseorg_data). map_filter_values_to_structure( EXPORTING iv_operation = const_omdo_core_op_read CHANGING cs_filters = str_dof_filter_vals ). DATA(lv_select_clause) = me->build_oper_field_select_string( iv_tabname = 'T024E' ). SELECT (lv_select_clause) FROM t024e INTO CORRESPONDING FIELDS OF TABLE lt_purchaseorg_data WHERE ekorg IN str_dof_filter_vals-purch_org->* AND bukrs IN str_dof_filter_vals-comp_code->*. cref_omdo_data->add_omdo_output_single( iv_tech_entity_type = is_entity_input_info-tech_entity_type iv_request_no = is_entity_input_info-request_no iref_data = lref_purchaseorg_data ). endmethod.
    1. Choose Back to return to the Methods tab.

    2. Locate the GET_DATA_FOR_READ_REQUEST.

    3. Choose Redefine Method from the tool bar.

    4. Clear the code within the method and copy paste the given code in method.

    5. Check syntax (Ctrl + F2).

    6. Choose Save.

  7. Redefine the method GET_OPER_FIELD_CATALOG_TABLES with the following code:

    Code Snippet
    123456789101112131415161718192021
    method /MFND/IF_CORE_OMDO_FIELD_CAT~GET_OPER_FIELD_CATALOG_TABLES. super->get_oper_field_catalog_tables( IMPORTING et_field_catalog_tables = et_field_catalog_tables et_exclusion_field_list = et_exclusion_field_list et_required_field_list = et_required_field_list ). et_field_catalog_tables = VALUE #( ( omdo_handler = me->clsname operation = const_omdo_core_op_read tabname = 'T024E' ) ). et_required_field_list = VALUE #( ( omdo_handler = me->clsname operation = const_omdo_core_op_read tabname = 'T024E' fieldname = 'EKORG' ) ( omdo_handler = me->clsname operation = const_omdo_core_op_read tabname = 'T024E' fieldname = 'EKOTX' ) ). endmethod.
    1. Choose Back to return to the Methods tab.

    2. Locate the GET_OPER_FIELD_CATALOG_TABLES

    3. Choose Redefine Method from the tool bar.

    4. Clear the code within the method and copy paste the given code in method.

    5. Check syntax (Ctrl + F2).

    6. Choose Save.

  8. Redefine the method GET_DATA_FILTER_LIST with the following code:

    Code Snippet
    1234567891011121314151617181920
    method /MFND/IF_CORE_OMDO_FILTER_SERV~GET_DATA_FILTER_LIST. REFRESH et_data_filters. et_data_filters = VALUE #( ( dof_name = 'PURCH_ORG' usage_tabname = 'T024E' usage_fieldname = 'EKORG' dof_group = /smfnd/cl_core_std_mdo_dofgrp=>std_dofgrp_distrmod omdo_handler = me->clsname operation = me->const_omdo_core_op_read ) ( dof_name = 'COMP_CODE' usage_tabname = 'T024E' usage_fieldname = 'BUKRS' dof_group = /smfnd/cl_core_std_mdo_dofgrp=>std_dofgrp_distrmod omdo_handler = me->clsname operation = me->const_omdo_core_op_read ) ). endmethod.
    1. Choose Back to return to the Methods tab.

    2. Locate the GET_DATA_FILTER_LIST.

    3. Choose Redefine Method from the tool bar.

    4. Clear the code within the method and copy paste the given code in method.

    5. Check syntax (Ctrl + F2).

    6. Choose Save.

  9. Activate the class.

    1. Go back to the class builder and Activate the entire class.

    2. Choose the Activate button (Ctrl+F3) and choose Enter on the pop-up window.

    3. Save as a local object.

      You should have coded four methods and defined two attributes.

      In the Methods tab, four methods are shown and two attributes are defined.

Task 2: Perform oMDO Object Configuration

Note

For the training, a mobile application (ZIAM_##_SERVICE_ASSET_MANAGER) is already created by copying a standard mobile app.

Note that the custom App is only for training purposes, in a project implementation you will directly work with the standard Mobile App.

This task involves the configuration of the oMDO Object. This includes configuration for data extraction and distribution logic. It determines the runtime behavior of the class created in the previous step.

Steps

  1. Create a new oMDO Object using the following details for your Mobile Application ZIAM-##.

    FieldValueExplanation
    oMDO IDZIAM150_##_PURCHASE_ORG 
    DescriptionZIAM150_## - Purchase Organization 
    Mobile ApplicationZIAM-## 
    oMDO HandlerZIAM_##_CL_MM_PURCHASE_ORG_OD (class created in previous task) 
    Process FlowBasic Process Flow without Key ListDecided based on the super class /MFND/CL_CORE_OMDO_BASIC_HNDLR
    Exempt Read Entity RequestNot Checked (false) 
    Enable Client State Tracking.CheckedTracks data downloaded to the device. Keys are compared during the next sync.
    Enable periodic refresh.Checked 
    Refresh frequency.720 
    Refresh on User Change.Not checkedApplicable for device sharing scenario. The data remains the same for multiple users as long as the user parameter for plant and company code are the same.
    Optimal Client State ReuseCheckedApplicable if "Enable Client State Tracking" is set to True. If there is no change in data, it skips the update of the client state keys in the DB and updates a counter.
    Sync Session Max Idle Time120Estimated maximum duration of sync for the oMDO
    Sync Priority.1

    Represents the processing sequence for read requests in a batch.

    For config data (with no dependency) we generally configure it as "1" and include in the first batch in Offline Access INI file.

    If the Entity has a dependency, ensure the number is higher than the source entity.

    1. Log in to the SAP GUI.

    2. Enter /n/syclo/configpanel to launch the ConfigPanel.

    3. Once you are within the Config Panel (Web Dynpro opens in Browser), choose oData Mobile Data Object Configuration in the oData Channel Integration settings section.

    4. Next, use the Mobile Application Filter dropdown to choose your mobile application IAM150-## (ZIAM_##_ASSET_MANAGER). It is important that you choose the correct mobile app name.

      The General Setting tab is selected.
    5. Select the mobile app and expand control on the left-hand side to view the oData Mobile data objects (oMDOs).

    6. Choose the Create button to create a new oMDO Object using the data given in the preceding table.

    7. Choose the Technical Model Info tab to view the technical entities exposed from oMDO Class Handler DEFINE_BO_ENTITY_MODEL.

    8. Choose the Data Filter and check the filters. Initially do not configure the filters, however once you have it working. You can configure the COMPANY_CODE filter and explore options using static and user parameter filters.

    9. Choose the Field Selection and choose the EKORG, EKOTX, BUKRS fields.

      The Field Selection tab is selected.
  2. Save your changes and assign them to a request.

    1. Choose the Save button to save the changes.

    2. If you have already created a customizing request, assign this and go to the next task.

    3. If you have not created a customizing request in an earlier exercise, in the pop-up window choose Create Request to capture the configuration changes into a transport.

    4. Provide a short description (IAM150-## config changes) in pop-up window.

    5. Choose the Create button.

    6. Once the Change Request Number is copied back to the pop-up, choose the Continue button to complete saving changes.

Task 3: Create a Custom App Feature

This task involves creating a custom app feature to which the Entities and oMDO can be assigned. The app feature allows you to logically group all your features together.

Steps

  1. Create a custom app feature.

    Use the following data:

    App Feature IDActiveDescription
    Z_CA_CORE_DATA_IAM150CheckedCustom Data for IAM150 Training

    1. Log in to the SAP GUI.

    2. Enter /n/syclo/configpanel to launch the ConfigPanel.

    3. Once you are within the Config Panel (Web Dynpro opens in Browser), choose Mobile Application Configuration.

    4. Choose your mobile application and open the Features tab.

    5. Choose the Change button.

    6. Choose the Add feature button.

    7. Enter the information from the preceding table.

    8. Choose Save to save your changes.

      The features tab is selected. The UI elements mentioned in the stepas are highlighted.

Task 4: oMDO Model Configuration

This task involves the configuration of the oMDO Model. This includes creation of oData Model definition for entity type, entity set, association, association set, navigation property, and so on.

Steps

  1. Create the oMDO Model for your mobile application.

    Use the following details.

    FieldValue
    Entity Type NameZ_##_PurchaseOrganization (Note: singular)
    Mobile ApplicationZIAM_##_SERVICE_ASSET_MANAGER
    oData Service IDZIAM150_INVENTORY_MANAGER_##-0001 (** make sure you choose the Asset Manager Mobile App Service in the dropdown)
    oMDO IDZIAM150_##_PURCHASE_ORG (oMDO Object created in previous task)
    oMDO Entity TypePURCHASEORG
    Entity Set Name.Z_##_PurchaseOrganizations (Note: plural)
    ActiveYes
    App Feature ID

    Z_CA_CORE_DATA_IAM150

    Assign to the feature created in the previous step.

    1. Choose the ConfigPanel Home button.

    2. Choose oData Model Configuration in the oData Channel Integration Settings section.

    3. Once you are within the mobile application oData Mode Details, use the Mobile Application Filter dropdown to choose your mobile application IAM150-## (ZIAM_##_ASSET_MANAGER)

    4. Expand your application and choose the Create button and enter the data given in the table.

  2. Add the following properties to the oData Model:

    Property NameoMDO Field NameEdm TypeKey
    PurchasingOrgEKORGEdm.StringX
    DescriptionEKOTXEdm.String 
    CompanyCodeBUKRSEdm.String 
    1. Choose the Property List tab.

    2. Choose Add Property and add the properties as given in the properties table.

  3. Save your changes.

    1. Choose the Save button at the top of the screen to save your changes (use the same Request you created previously).

      The Property List tab is selected.

Task 5: Persona Assignment

This task involves the assignment of the oMDO → Feature and then Feature → User Persona.

Steps

  1. Assign oMDO to Feature.

    1. Log in to the SAP GUI.

    2. Enter /n/syclo/configpanel to launch the ConfigPanel.

    3. Once you are within the Config Panel (Web Dynpro opens in Browser), choose Component Assignment in the General Info section.

    4. Once you are within the Application Assignment Configuration, on your Mobile Application chooseZIAM_##_ASSET_MANAGER (IAM150-##)

    5. In the next screen, choose the oMOD Assignment tab.

    6. Choose the Change button.

    7. In the App Feature Id dropdown and select Z_CA_CORE_DATA_IAM150.

    8. In the oMDO ID dropdown, choose ZIAM150_##_PURCHASE_ORG.

    9. In the filtered Assignment List Table, set both In-Scope and Active Flag checkboxes to True.

    10. Choose Save to complete the assignment oMDO to the feature.

      To complete the assignment, choose Save.
  2. Assign Feature to Persona.

    1. Choose the User Personas tab.

    2. In the User Persona dropdown, choose INVENTORY_CLERK persona.

    3. In the App Feature Id dropdown, choose Z_CA_CORE_DATA_IAM150.

    4. In the Feature Assignment table, set both In Scope and Activate Flag checkboxes to True.

    5. Choose the Save button to save your changes to complete assignment of the feature to the persona.

      To complete the assignment, choose Save.

Task 6: Test Your Changes Using the Gateway Client

Steps

  1. Clear oData Service cache for your service.

    1. Log in to the SAP GUI and enter the transaction code /n/IWFND/MAINT_SERVICE and choose Enter.

    2. Navigate to the service ZIAM_##_ASSET_MANAGER version 1.

      Note that the ZIAM_##_INVENTORY_MANAGER Service is a subset of this composite service. The cache clean-up of Asset Manager Service will automatically cascade to the subset.

      Note

      For additional information, check the oData Service Assignment in Config Panel to see how the Services are assigned to your Mobile Applications and the Composite Settings.

    3. In the System Aliases section, choose the Service Implementation button.

    4. In the next screen, choose Cleanup Cache.

    5. Back on the /IWFND/MAINT_SERVICE screen, choose the Load Metadata button.

      Choose Service Implementation, then choose Load Metadata.A dialog box shows the message that the metadata has been reloaded.

  2. Test the Service using Gateway Client.

    1. While in the /IWFND/MAINT_SERVICE in the ICF Nodes section (at bottom left), choose the SAP Gateway Client to test the service using the Gateway Client.

      Note

      When you launch the Gateway Client (/IWFND/GW_CLIENT) via Maintain Service (/IWFND/MAINT_SERVICE) the Request URI is defaulted else you can enter /sap/opu/odata/sap/ZIAM_##_SAP_ASSET_MANAGER/?$format=xml

    2. Choose Execute to verify the service is working.

      Verify the ~status_code = 200

    3. From the Application toolbar, choose the EntitySets button.

    4. Choose Z_##_PurchaseOrganizations Entity set.

    5. The Request URI is updated to fetch the PurchaseOrganizations Entity set /sap/opu/odata/sap/ZIAM_##_ASSET_MANAGER/PurchaseOrganizations

    6. Choose Execute.

      Screenshot of the SAP Gateway Client showing the XML file.
    7. In the HTTP Response, verify that ~status_code = 200 and some data is returned in the response window.

Task 7: Sync Service to Update Metadata in BAS

Steps

  1. Once you have successfully tested PurchaseOrganizations via SAP Gateway, you can sync the service in BAS to update the Metadata.

    1. Log in to the SAP Business Application Studio.

    2. Open Project ZSAMComponent.

    3. Navigate to ServicesAssetManager.service.

    4. Once within the AssetManager.service, choose the Sync Service button to update the Model.

    5. Verify the AssetManager.xml to see if the PurchaseOrganizations is downloaded.

Create a Purchase Requisition via SAP GUI

Business Scenario

In this exercise, you first create a Purchase Requisition in SAP GUI so that we can test the download of Purchase Requisition to Mobile Device. Later in this unit, we create the Purchase Requisition from Mobile Device.

Note

The steps below are giving a guide so that you can perform this exercise in your own system landscape.

Steps

  1. Create a Purchase Requisition in SAP GUI TCode ME51n.

    Note

    We use this data later when creating the Purchase Requisition from the Mobile Client.

    FieldValue
    Purchase Document TypeNB (default selection)
    MaterialA500-00
    Quantity10 (Unit PC filled automatically)
    Plant1010
    Storage Location0001
    Purchase Organization1010
    RequisitionerIAM150-##
    FieldValue
    Item10 (populated automatically)
    Purchase GroupZ00 (derived from Plant)
    Short TextOil pump 500/00
    Unit of MeasurePC (derived from Material)
    Delivery DateCurrent date
    Delivery Date CategoryD (default value–Day Format)
    Material GroupL003 (derived from Material)
    Valuation Price46.50 (derived from Material Accounting view)
    CurrencyEUR
    Price Unit1
    Created ByCurrent user

    This data is populated automatically.

    Screenshot of the Create Purchase Requisition screen.
    1. Execute transaction ME51N.

    2. Enter the data as given in the tables above.

Download Purchase Requisition (Part-1: Back-end)

Note

Use Transaction SE24 and there the reference class handler /MERP/CL_MM_PURCHASE_REQ_OD to create your copy Zxxx files. The code snippets provided in this handbook are examples for your reference only. Copy the required coding from the reference class.

Note

The steps below are giving a guide so that you can perform this exercise in your own system landscape.

Task 1: Create oMDO Class Handler: Development Tasks

Steps

  1. Create an oMDO Class for fetching Purchase Requisition data from SAP with the following data:

    FieldValue
    DescriptionPurchase Requisition OMDO Handler for IAM_##
    Instance GenerationPublic
    Usual ABAP Class<Select the radio button>
    Final<Uncheck the checkbox>
    1. Log in to the SAP system and navigate to transaction code SE24.

    2. Enter ZIAM_##_CL_MM_PURCHASE_REQ.

    3. Choose Create.

    4. In the pop-up window, choose (the default) Object Type Class radio button.

    5. Choose the Enter button.

    6. Enter the details as given in the table.

    7. Select the Save button.

    8. On the next pop-up window, choose the Local Object button and choose Save (or enter Package as $TMP).

  2. Set the super class of this class to /MERP/CL_CORE_OMDO_HNDLER_BASE.

    1. Once you are in the class, choose the Properties tab.

    2. Choose the Superclass button.

    3. Enter /MERP/CL_CORE_OMDO_HNDLER_BASE in the superclass name.

    4. Verify that the Final check box is unchecked.

    5. Choose the Save button.

      At this point, you notice that there are few interfaces and method loaded in the corresponding tabs.

      Note

      Set up your environment for better legibility by choosing in the menu bar UtilitiesSettingsClass Builder tab, check the Display Aliases and Group by Interfaces and Superclasses and choose Enter.

  3. Add Object Types.

    Use the following data:

    TypeProtectedAssociated TypeDescription
    GTYP_INPUT_FILTER_VALS_STRProtected Purchase Requisition Filters oMDO
    GTYP_OBJKEY_STRProtected  
    GTYP_PREQ_KEY_STRProtected  
    GTYP_PREQ_HDR_KEY_STRProtected  
    GTYP_PREQ_ACC_ASGN_KEY_STRProtected  
    GTYP_PREQ_KEY_TABProtected  

    1. Choose the Types tab.

    2. Enter the data as given in the preceding table.

    3. Choose Direct Type Entry.

    4. If prompted, choose Save changes.

    5. In the protected sectionenter the following code.

      Code Snippet
      123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
      types: BEGIN OF gtyp_dof_filter_vals_str, object_distribution_mode TYPE REF TO /mfnd/core_range_tab, preq_doc_cat TYPE REF TO /mfnd/core_range_tab, preq_doc_type TYPE REF TO /mfnd/core_range_tab, preq_date TYPE REF TO /mfnd/core_range_tab, open_items_only TYPE REF TO /mfnd/core_range_tab, purch_group TYPE REF TO /mfnd/core_range_tab, purch_org TYPE REF TO /mfnd/core_range_tab, purch_agreement TYPE REF TO /mfnd/core_range_tab, vendor TYPE REF TO /mfnd/core_range_tab, suppl_plnt TYPE REF TO /mfnd/core_range_tab, created_by TYPE REF TO /mfnd/core_range_tab, material TYPE REF TO /mfnd/core_range_tab, matl_group TYPE REF TO /mfnd/core_range_tab, item_cat TYPE REF TO /mfnd/core_range_tab, acctasscat TYPE REF TO /mfnd/core_range_tab, trackingno TYPE REF TO /mfnd/core_range_tab, delete_ind TYPE REF TO /mfnd/core_range_tab, preq_on_demand TYPE REF TO /merp/mm_preq_ondemand_tab, user_location TYPE REF TO /merp/mm_user_location_tab, user_rule_enabled TYPE REF TO /mfnd/core_range_tab, disable_fetch TYPE REF TO /mfnd/core_range_tab, preq_status TYPE REF TO /mfnd/core_range_tab, header_text_id TYPE REF TO /mfnd/core_range_tab, item_text_id TYPE REF TO /mfnd/core_range_tab, max_no_of_hits TYPE REF TO /mfnd/core_range_tab, automatic_source TYPE REF TO /mfnd/core_range_tab, skip_item_with_error TYPE REF TO /mfnd/core_range_tab, END OF gtyp_dof_filter_vals_str . types: BEGIN OF gtyp_input_filter_vals_str, banfn TYPE REF TO /mfnd/core_range_tab, END OF gtyp_input_filter_vals_str . types: BEGIN OF gtyp_objkey_str, banfn TYPE banfn, bnfpo TYPE bnfpo, packno TYPE packno, END OF gtyp_objkey_str . types: BEGIN OF gtyp_preq_key_str, banfn TYPE banfn, bnfpo TYPE bnfpo, END OF gtyp_preq_key_str . types: BEGIN OF gtyp_preq_hdr_key_str, banfn TYPE banfn, END OF gtyp_preq_hdr_key_str . constants CONST_PREQ_ENTITY type /MFND/CORE_TECH_ENTITY_TYP_DTE value 'PREQ' ##NO_TEXT. constants CONST_PREQ_HDR_ENTITY type /MFND/CORE_TECH_ENTITY_TYP_DTE value 'PREQHDR' ##NO_TEXT. constants CONST_PREQ_ACC_ASGN_ENTITY type /MFND/CORE_TECH_ENTITY_TYP_DTE value 'PREQACCASGN' ##NO_TEXT. types: gtyp_objkey_tab TYPE STANDARD TABLE OF gtyp_objkey_str . types: gtyp_hdrkey_tab TYPE STANDARD TABLE OF gtyp_preq_hdr_key_str . types: gtyp_preq_key_tab TYPE STANDARD TABLE OF gtyp_preq_key_str . data STR_DOF_FILTER_VALS type GTYP_DOF_FILTER_VALS_STR . data STR_INPUT_FILTER_VALS type GTYP_INPUT_FILTER_VALS_STR . data GREF_OMDO_DATA type ref to /MFND/CL_CORE_OMDO_DATA . data GREF_PREQ_BADI type ref to /MERP/MM_OMDO_PREQ_BADI . data GV_MAX_NO_OF_HIT type SY-INDEX .
    6. Save changes.

  4. Add attributes to your class with the following details.

    Attribute NameLevelVisibilityAssociated TypeDescriptionInitial Value
    CONST_PREQ_ENTITYConstantPublic/MFND/CORE_TECH_ENTITY_TYP_DTEoMDO - Technical Entity Type'PREQ'
    CONST_PREQ_HDR_ENTITConstantPublic/MFND/CORE_TECH_ENTITY_TYP_DTEoMDO - Technical Entity Type'PREQHDR'
    CONST_PREQ_ACC_ASGN_ENTITYConstantPublic/MFND/CORE_TECH_ENTITY_TYP_DTEoMDO - Technical Entity Type'PREQACCASGN'
    CONST_PREQ_NOTE_ENTITYConstantPublic/MFND/CORE_TECH_ENTITY_TYP_DTEoMDO - Technical Entity TypePREQNOTE
    STR_DOF_FILTER_VALSInstance AttributeProtectedGTYP_DOF_FILTER_VALS_STR  
    STR_INPUT_FILTER_VALSInstance AttributeProtectedGTYP_INPUT_FILTER_VALS_STR  

    Note

    Single quotes are required for the Initial Value 'PREQ', 'PREQHDR' and 'PREQACCASGN'

    1. Choose the Attributes tab.

    2. Enter the data as given in the preceding table.

  5. Redefine the method DEFINE_BO_ENTITY_MODEL with the following code:

    Code Snippet
    123456789
    method /MFND/IF_CORE_OMDO_BO_MODEL~DEFINE_BO_ENTITY_MODEL. CLEAR et_bo_entities. et_bo_entities = VALUE #( ( tech_entity_type = const_preq_entity ref_struct = '/MERP/MM_PURCHASE_REQ_ENTY_STR' flag_lead_entity = abap_true ) ( tech_entity_type = const_preq_hdr_entity ref_struct = '/MERP/MM_PURCHASE_REQ_ENTY_STR' ) ( tech_entity_type = const_preq_acc_asgn_entity ref_struct = '/MERP/MM_PREQ_ACCASGN_ENTY_STR' ) ). endmethod.
    1. Choose the Methods tab.

    2. Choose the Find button and search for Method DEFINE_BO_ENTITY_MODEL.

    3. Choose the Redefine button.

    4. Clear the code within the method and copy paste the given code in method.

    5. Check syntax (Ctrl + F2).

    6. Choose Save.

    7. Repeat the steps for the rest of the methods.

  6. Redefine the method GET_OBJKEYS_BY_DISTRIB_RULES with the following code:

    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
    METHOD get_objkeys_by_distrib_rules. "Insert Start S4MERP SP11 bugid S4MOBADDON-2931 DATA: ls_preq TYPE gtyp_preq_key_str, ls_preq_hdr TYPE gtyp_preq_hdr_key_str, ls_preq_acc_asgn TYPE gtyp_preq_acc_asgn_key_str, lv_object_key TYPE /mfnd/core_bo_object_key_dte. *Get OnDemand List READ TABLE str_dof_filter_vals-preq_on_demand->* INTO DATA (ls_preq_on_demand) INDEX 1. * Get Purchase Requisition(PR) Keylist (EBAN) get_objkeys_preqs( EXPORTING is_entity_input_info = is_entity_input_info iref_omdo_data = cref_omdo_data IMPORTING et_objkeys = DATA(lt_objkeys) ). APPEND INITIAL LINE TO tab_bo_entity_keys_distr_rule ASSIGNING FIELD-SYMBOL(). APPEND INITIAL LINE TO tab_bo_entity_keys_distr_rule ASSIGNING FIELD-SYMBOL(). -tech_entity_type = const_preq_entity. -key_field_info = build_key_field_info_list( is_key_struct = ls_preq ). -tech_entity_type = const_preq_hdr_entity. -key_field_info = build_key_field_info_list( is_key_struct = ls_preq_hdr ). LOOP AT lt_objkeys ASSIGNING FIELD-SYMBOL(). DATA(lv_preq_key) = CONV char255( -banfn && -bnfpo ). INSERT lv_preq_key INTO TABLE -object_keylist. DATA(lv_preqhdr_key) = CONV char255( -banfn ). INSERT lv_preqhdr_key INTO TABLE -object_keylist. ENDLOOP. DELETE ADJACENT DUPLICATES FROM -object_keylist COMPARING ALL FIELDS. DELETE ADJACENT DUPLICATES FROM -object_keylist COMPARING ALL FIELDS. * Get PR Account Assignment Keylist(EBKN) IF ls_preq_on_demand-preq_account_assignment = 'X'. get_objkeys_preq_acc_asgn( EXPORTING it_objkeys = lt_objkeys IMPORTING et_preq_acc_asgn_keys = DATA(lt_preq_acc_asgn_keys) ). APPEND INITIAL LINE TO tab_bo_entity_keys_distr_rule ASSIGNING FIELD-SYMBOL(). -tech_entity_type = const_preq_acc_asgn_entity. -key_field_info = build_key_field_info_list( is_key_struct = ls_preq_acc_asgn ). LOOP AT lt_preq_acc_asgn_keys ASSIGNING FIELD-SYMBOL(). lv_object_key = CONV char255( -banfn && -bnfpo && -zebkn ). INSERT lv_object_key INTO TABLE -object_keylist. ENDLOOP. ENDIF. ENDMETHOD.
    1. Perform the steps as described in the previous step.

  7. Redefine the method INITIALIZE_REQUEST_PROCESSING with the following code:

    Code Snippet
    123456789101112131415161718192021222324252627282930313233
    METHOD initialize_request_processing. "Set reference to oMDO container gref_omdo_data = cref_omdo_data. "DOF filters CREATE DATA: str_dof_filter_vals-preq_on_demand, str_dof_filter_vals-ondemand_mapping, str_dof_filter_vals-user_location. map_filter_values_to_structure( EXPORTING iv_operation = omdo_operation CHANGING cs_filters = str_dof_filter_vals ). IF omdo_operation = const_omdo_core_op_read AND str_dof_filter_vals-max_no_of_hits->* IS NOT INITIAL. /smfnd/cl_core_mdo_tools=>get_simple_val_from_range( EXPORTING it_range_table = str_dof_filter_vals-max_no_of_hits->* IMPORTING ev_low = gv_max_no_of_hit ). LOOP AT str_dof_filter_vals-created_by->* ASSIGNING FIELD-SYMBOL(). IF -low = 'SY-UNAME'. -low = sy-uname. ENDIF. ENDLOOP. ENDIF. "URL Input $Filters LOOP AT cref_omdo_data->tab_odata_v2_req_info ASSIGNING FIELD-SYMBOL(). cref_omdo_data->map_entity_input_field_filters( EXPORTING iv_request_no = -request_no iv_tech_entity_type = -tech_entity_type CHANGING cs_filters = str_input_filter_vals ). ENDLOOP. ENDMETHOD.
    1. Perform the steps as described in the previous step.

  8. Redefine the method GET_OPER_FIELD_CATALOG_TABLES with the following code:

    Code Snippet
    123456789101112131415161718192021222324252627
    METHOD /mfnd/if_core_omdo_field_cat~get_oper_field_catalog_tables. "Insert Start S4MERP SP11 bugid S4MOBADDON-2931 super->get_oper_field_catalog_tables( IMPORTING et_field_catalog_tables = et_field_catalog_tables et_exclusion_field_list = et_exclusion_field_list et_required_field_list = et_required_field_list ). et_field_catalog_tables = VALUE #( ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBAN' ) ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBKN' ) ). et_required_field_list = VALUE #( "Purchase Requisition (PR) ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBAN' fieldname = 'BANFN' ) ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBAN' fieldname = 'BNFPO' ) ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBAN' fieldname = 'SPRAS' ) "PR Account Assignment ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBKN' fieldname = 'BANFN' ) ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBKN' fieldname = 'BNFPO' ) ( omdo_handler = clsname operation = const_omdo_core_op_read tabname = 'EBKN' fieldname = 'ZEBKN' ) ). "Insert End S4MERP SP11 bugid S4MOBADDON-2931 ENDMETHOD.
    1. Perform the steps as described in the previous step.

  9. Redefine the method GET_DATA_FILTER_LIST with the following code:

    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
    METHOD /mfnd/if_core_omdo_filter_serv~get_data_filter_list. REFRESH et_data_filters. et_data_filters = VALUE #( "Read Operation ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'OBJECT_DISTRIBUTION_MODE' dof_group = /mfnd/cl_core_std_omdo_dofgrp=>std_dofgrp_distrmod usage_tabname = '/MERP/CORE_OMDO_DISTR_STR' usage_fieldname = 'GEN_ASGMNT_TYPE' mandatory = abap_true ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'PREQ_ON_DEMAND' usage_tabname = '/MERP/MM_PREQ_ONDEMAND_STR' dof_group = /mfnd/cl_core_std_omdo_dofgrp=>std_dofgrp_dataseg dof_type = /mfnd/if_core_omdo_const=>omdo_doftype_tablerule filter_status = /mfnd/if_core_omdo_const=>filter_stat_std tech_name_only = 'X') ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'USER_LOCATION' usage_tabname = '/MERP/MM_USER_LOCATION_STR' dof_type = const_filter_type_table dof_group = /mfnd/cl_core_std_omdo_dofgrp=>std_dofgrp_dataseg ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'USER_RULE_ENABLED' usage_tabname = '/SYCLO/CA000P' usage_fieldname = 'PARAM_VALUE' dof_group = /mfnd/cl_core_std_omdo_dofgrp=>std_dofgrp_dataseg ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'PREQ_DOC_CAT' usage_tabname = 'EBAN' usage_fieldname = 'BSTYP' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'PREQ_DOC_TYPE' usage_tabname = 'EBAN' usage_fieldname = 'BSART' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'PREQ_DATE' usage_tabname = 'EBAN' usage_fieldname = 'BADAT' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'OPEN_ITEMS_ONLY' usage_tabname = 'EBAN' usage_fieldname = 'EBAKZ' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'PURCH_GROUP' usage_tabname = 'EBAN' usage_fieldname = 'EKGRP' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'PURCH_ORG' usage_tabname = 'EBAN' usage_fieldname = 'EKORG' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'PURCH_AGREEMENT' usage_tabname = 'EBAN' usage_fieldname = 'KONNR' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'VENDOR' usage_tabname = 'EBAN' usage_fieldname = 'LIFNR' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'SUPPL_PLNT' usage_tabname = 'EBAN' usage_fieldname = 'RESWK' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'CREATED_BY' usage_tabname = 'EBAN' usage_fieldname = 'ERNAM' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'MATERIAL' usage_tabname = 'EBAN' usage_fieldname = 'MATNR' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'MATL_GROUP' usage_tabname = 'EBAN' usage_fieldname = 'MATKL' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'ITEM_CAT' usage_tabname = 'EBAN' usage_fieldname = 'PSTYP' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'ACCTASSCAT' usage_tabname = 'EBAN' usage_fieldname = 'KNTTP' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'TRACKINGNO' usage_tabname = 'EBAN' usage_fieldname = 'BEDNR' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'DELETE_IND' usage_tabname = 'EBAN' usage_fieldname = 'LOEKZ' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'DISABLE_FETCH' usage_tabname = '/MFND/CORE_BOOLEAN_STR' usage_fieldname = 'BOOLEAN' ) ( omdo_handler = clsname operation = const_omdo_core_op_read dof_name = 'MAX_NO_OF_HITS' usage_tabname = 'SYST' usage_fieldname = 'INDEX' filter_status = /syclo/cl_core_constants=>filter_stat_std ) ). ENDMETHOD.
    1. Perform the steps as described in the previous step.

  10. Next create the method GET_OBJKEYS_PREQS with the following code:

    Code Snippet
    1234567891011121314151617181920
    METHOD get_objkeys_preqs. REFRESH et_objkeys. DATA: lt_objkeys_tmp TYPE gtyp_objkey_tab, lt_objkeys TYPE gtyp_objkey_tab. IF /mfnd/cl_core_constants=>omdo_filter IN str_dof_filter_vals-object_distribution_mode->*. get_objkeys_for_distr_mode_1( IMPORTING et_object_keylist = lt_objkeys_tmp ). APPEND LINES OF lt_objkeys_tmp TO lt_objkeys. ENDIF. IF /mfnd/cl_core_constants=>dep_queue IN str_dof_filter_vals-object_distribution_mode->*. CLEAR lt_objkeys_tmp. get_objkeys_for_distr_mode_2( IMPORTING et_object_keylist = lt_objkeys_tmp ). APPEND LINES OF lt_objkeys_tmp TO lt_objkeys. flag_bo_distr_key_calc_accumu = abap_true. ENDIF. et_objkeys = lt_objkeys. ENDMETHOD.
    1. Perform the steps as described in the previous step.

  11. Create the method GET_OBJKEYS_FOR_DISTR_MODE_1 with the following code:

    Code Snippet
    123456789101112131415161718192021222324252627282930313233
    METHOD get_objkeys_for_distr_mode_1. REFRESH et_object_keylist. IF str_dof_filter_vals-user_location->* IS NOT INITIAL. READ TABLE str_dof_filter_vals-user_rule_enabled->* ASSIGNING FIELD-SYMBOL() INDEX 1. DATA(lv_user_rule_enabled) = -low. ENDIF. DATA lt_objkeys TYPE gtyp_objkey_tab. IF str_dof_filter_vals-user_location->* IS NOT INITIAL AND lv_user_rule_enabled = abap_true. SELECT banfn bnfpo packno FROM eban "#EC CI_NOORDER INTO TABLE lt_objkeys UP TO gv_max_no_of_hit ROWS FOR ALL ENTRIES IN str_dof_filter_vals-user_location->* WHERE werks = str_dof_filter_vals-user_location->*-werks AND lgort = str_dof_filter_vals-user_location->*-lgort AND bstyp IN str_dof_filter_vals-preq_doc_cat->* AND bsart IN str_dof_filter_vals-preq_doc_type->* AND badat IN str_dof_filter_vals-preq_date->* AND ekorg IN str_dof_filter_vals-purch_org->* AND ekgrp IN str_dof_filter_vals-purch_group->* AND lifnr IN str_dof_filter_vals-vendor->* AND reswk IN str_dof_filter_vals-suppl_plnt->* AND ernam IN str_dof_filter_vals-created_by->* AND matnr IN str_dof_filter_vals-material->* AND matkl IN str_dof_filter_vals-matl_group->* AND knttp IN str_dof_filter_vals-acctasscat->* AND loekz IN str_dof_filter_vals-delete_ind->* %_HINTS HDB '&max_in_blocking_factor 32767&' ##NO_TEXT. "#EC CI_HINTS. ENDIF. APPEND LINES OF lt_objkeys TO et_object_keylist. ENDMETHOD.
    1. Perform the steps as described in the previous step.

  12. Create the method GET_OBJKEYS_FROM_DEP_QUEUE with the following code:

    Code Snippet
    123456789101112131415161718192021222324252627282930
    Method GET_OBJKEYS_FROM_DEP_QUEUE. "Insert Start S4MERP SP11 bugid S4MOBADDON-2931 REFRESH et_objkeys. "Get table of Dep. Keylits, 1 row per Origin DATA (lt_depobj_keylists) = /mfnd/cl_core__depobj_queue_mgr=>get_user_dep_objkeys_by_orig( iv_user_guid = user_guid iv_dep_omdo_id = str_omdo_general_settings-omdo_id iv_dep_tech_entire_type = const_preq_entity ) . IF gref_preq_badi IS NOT INITIAL CALL BADI gref_preq_badi->get_objkeys_from_dep_queue EXPORTING iref_cmdo_data = gref_omdo_data iv_user_guid = user_guid iv_omdo_id = str_omdo_general_setting-omdo_id iv_tech_entity_type = const_preq_entity CHANGING ct_dep_object_keylists = lt_depobj_keylists. ENDIF LOOP AT lt_depobj_keylists ASSIGNING FIELD-SYMBOL(<keylist>). LOOP AT <keylist>-key_list ASSIGNING FIELD-SYMBOL(<depobj_key>). APPEND <depobj_key> TO et_objkeys. ENDLOOP. ENDLOOP. "Insert End S4MERP SP11 bugid S4MOBADDON-2931 ENDMETHOD
    1. Perform the steps as described in the previous step.

  13. Create the method GET_OBJKEYS_FOR_DISTR_MODE_2 with the following code:

    Code Snippet
    123456789101112131415161718
    METHOD get_objkeys_for_distr_mode_2. REFRESH et_object_keylist. get_objkeys_from_dep_queue( IMPORTING et_objkeys = DATA(lt_objkeys) ). SORT lt_objkeys BY banfn. DELETE ADJACENT DUPLICATES FROM lt_objkeys COMPARING banfn. IF lt_objkeys IS NOT INITIAL. SELECT eban~banfn eban~bnfpo eban~packno FROM eban INTO TABLE et_object_keylist FOR ALL ENTRIES IN lt_objkeys WHERE eban~banfn = lt_objkeys-banfn %_HINTS HDB '&max_in_blocking_factor 32767&' ##NO_TEXT. "#EC CI_HINTS. ENDIF. ENDMETHOD.
    1. Perform the steps as described in the previous step.

  14. Create the method GET_OBJKEYS_PREQ_ACC_ASGN with the following code:

    Code Snippet
    1234567891011121314
    METHOD get_objkeys_preq_acc_asgn. CHECK it_objkeys IS NOT INITIAL. REFRESH et_preq_acc_asgn_keys. SELECT banfn bnfpo zebkn FROM ebkn INTO TABLE et_preq_acc_asgn_keys FOR ALL ENTRIES IN it_objkeys WHERE banfn = it_objkeys-banfn AND bnfpo = it_objkeys-bnfpo. "Insert End S4MERP SP11 bugid S4MOBADDON-2931 ENDMETHOD
    1. Perform the steps as described in the previous step.

  15. Redefine the method LOAD_ENTITY_DETAILS with the following code:

    Code Snippet
    123456789101112131415
    METHOD load_entity_details. CASE is_entity_input_info-tech_entity_type. WHEN const_preq_entity. get_preqs( EXPORTING is_entity_input_info = is_entity_input_info CHANGING cref_omdo_data = cref_omdo_data ). WHEN const_preq_hdr_entity. get_preqs_header( EXPORTING is_entity_input_info = is_entity_input_info CHANGING cref_omdo_data = cref_omdo_data ). WHEN const_preq_acc_asgn_entity. get_preq_acc_asgn( EXPORTING is_entity_input_info = is_entity_input_info CHANGING cref_omdo_data = cref_omdo_data ). ENDMETHOD.
    1. Perform the steps as described in the previous step.

  16. Create the method GET_PREQS with the following code:

    Code Snippet
    1234567891011121314151617181920212223242526272829303132
    METHOD get_preqs. "Tables & Structures DATA: lt_preq_data TYPE STANDARD TABLE OF /merp/mm_purchase_req_enty_str, lt_preq_keys TYPE STANDARD TABLE OF gtyp_preq_key_str. *---Main Section log_method_call( ). GET REFERENCE OF lt_preq_data INTO DATA(lref_preq_data). DATA(lref_object_keylist) = load_delta_load_keylist( iv_tech_entity_type = const_preq_entity ). IF lref_object_keylist->*-object_keylist IS NOT INITIAL. LOOP AT lref_object_keylist->*-object_keylist ASSIGNING FIELD-SYMBOL(). APPEND TO lt_preq_keys. ENDLOOP. DATA(lv_select_clause) = build_oper_field_select_string( iv_tabname = 'EBAN' iv_expanded_field_list = 'X' ). SELECT (lv_select_clause) FROM eban "#EC CI_HINTS INTO CORRESPONDING FIELDS OF TABLE lref_preq_data->* FOR ALL ENTRIES IN lt_preq_keys WHERE eban~banfn = lt_preq_keys-banfn AND eban~bnfpo = lt_preq_keys-bnfpo %_HINTS HDB '&max_in_blocking_factor 32767&' ##NO_TEXT. ENDIF. cref_omdo_data->add_omdo_output_single( iv_tech_entity_type = is_entity_input_info-tech_entity_type iv_request_no = is_entity_input_info-request_no iref_data = lref_preq_data ). ENDMETHOD.
    1. Perform the steps as described in the previous step.

  17. Next create the method GET_PREQS_HEADER with the following code:

    Code Snippet
    123456789101112131415161718192021222324252627282930
    METHOD get_preqs_header. "Tables & Structures DATA: lt_preq_data TYPE STANDARD TABLE OF /merp/mm_purchase_req_enty_str, lt_preq_keys TYPE STANDARD TABLE OF gtyp_preq_hdr_key_str. *---Main Section log_method_call( ). GET REFERENCE OF lt_preq_data INTO DATA(lref_preq_data). DATA(lref_object_keylist) = load_delta_load_keylist( iv_tech_entity_type = const_preq_hdr_entity ). IF lref_object_keylist->*-object_keylist IS NOT INITIAL. LOOP AT lref_object_keylist->*-object_keylist ASSIGNING FIELD-SYMBOL(). APPEND TO lt_preq_keys. ENDLOOP. LOOP AT lt_preq_keys ASSIGNING FIELD-SYMBOL(). APPEND INITIAL LINE TO lt_preq_data ASSIGNING FIELD-SYMBOL(). -banfn = -banfn. ENDLOOP. SORT lt_preq_data BY banfn. DELETE ADJACENT DUPLICATES FROM lt_preq_data COMPARING banfn. ENDIF. cref_omdo_data->add_omdo_output_single( iv_tech_entity_type = is_entity_input_info-tech_entity_type iv_request_no = is_entity_input_info-request_no iref_data = lref_preq_data ). ENDMETHOD.
    1. Perform the steps as described in the previous step.

  18. Next create the method GET_PREQ_ACC_ASGN with the following code:

    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435
    METHOD get_preq_acc_asgn. "Insert Start S4MERP SP11 bugid S4MOBADDON-2931 "Tables & Structures DATA: lt_preq_accasgn_data TYPE STANDARD TABLE OF /merp/mm_preq_accasgn_enty_str, lt_preq_accasgn_keys TYPE STANDARD TABLE OF gtyp_preq_acc_asgn_key_str. *---Main Section log_method_call( ). GET REFERENCE OF lt_preq_accasgn_data INTO DATA(lref_preq_accasgn_data). DATA(lref_object_keylist) = load_delta_load_keylist( iv_tech_entity_type = const_preq_entity ). IF lref_object_keylist->*-object_keylist IS NOT INITIAL. LOOP AT lref_object_keylist->*-object_keylist ASSIGNING FIELD-SYMBOL(). APPEND TO lt_preq_accasgn_keys. ENDLOOP. DATA(lv_select_clause) = build_oper_field_select_string( iv_tabname = 'EBKN' iv_expanded_field_list = 'X' ). SELECT (lv_select_clause) FROM ebkn INTO CORRESPONDING FIELDS OF TABLE lref_preq_accasgn_data->* FOR ALL ENTRIES IN lt_preq_accasgn_keys WHERE banfn = lt_preq_accasgn_keys-banfn AND bnfpo = lt_preq_accasgn_keys-bnfpo AND zebkn = lt_preq_accasgn_keys-zebkn %_HINTS HDB '&max_in_blocking_factor 32767&' ##NO_TEXT. "#EC CI_HINTS. ENDIF. cref_omdo_data->add_omdo_output_single( iv_tech_entity_type = is_entity_input_info-tech_entity_type iv_request_no = is_entity_input_info-request_no iref_data = lref_preq_accasgn_data ). "Insert End S4MERP SP11 bugid S4MOBADDON-2931
    1. Perform the steps as described in the previous step.

  19. Activate the class.

    1. Go back to the class builder.

    2. Choose the Activate button (Ctrl+F3) and choose Enter on the pop-up window.

      In the screenshot, the Methods tab is highlighted.

Task 2: Perform oMDO Object Configuration

Note

For the training, a mobile application (ZIAM_##_SERVICE_ASSET_MANAGER) is already created by copying a standard mobile app. (## refers to your group number).

Note that the custom app is only for training purposes, in a project implementation you work directly with the standard mobile app.

This task involves the configuration of the oMDO Object. This includes configuration for data extraction and distribution logic. It determines the runtime behavior of the class created in the previous step.

Steps

  1. Create a new oMDO Object using the following details for your Mobile Application ZIAM-##.

    FieldValueExplanation
    oMDO IDZIAM150_##_PURCHASE_REQ 
    DescriptionZIAM150_## - Purchase Requisition 
    Mobile ApplicationZIAM-## 
    oMDO HandlerZIAM_##_CL_MM_PURCHASE_REQ (class created in previous task)Decided by super class /MERP/CL_CORE_OMDO_HNDLER_BASE
    Process FlowStandard Flow using Key List 
    Exempt Read Entity RequestFalse 
    Enable Client State Tracking.Checked 
    Enable periodic refresh.False 
    Refresh frequency.False 
    Optimal Client StateChecked 
    Support Delta SyncFalseWhen an Exchange Object is created and assigned, we set this to True. For now, set to False
    Data Distribution ModeAlways perform distrib. key calculation 
    Delta Object Key List Setup ModeDifference of Current and Last Data Distribution Keylist 
    Enable Paging.Checked 
    Paging Package size5000Number of records in each package
    Sync Session Max Idle Timeout120 
    Sync Priority.440Higher number as we want to download after other objects.
    1. Log in to the SAP GUI.

    2. Enter /n/syclo/configpanel to launch the ConfigPanel.

    3. Once you are within the Config Panel (Web Dynpro opens in Browser), choose oData Mobile Data Object Configuration in the oData Channel Integration Settings section.

    4. Use the Mobile Application Filter dropdown to choose your mobile application IAM150-## (ZIAM_##_ASSET_MANAGER).

      It is important that you choose the correct mobile app name.

    5. Select the mobile app and expand control on the left-hand side to view the oData Mobile data objects (oMDOs).

    6. Choose the Create button to create a new oMDO Object using the data given in the preceding table.

      On the screenshot, the General Settings tab is selected.
    7. Choose the Technical Model Info tab to view the Technical Entities exposed from oMDO Class Handler DEFINE_BO_ENTITY_MODEL.

    8. Navigate to the Field Selection tab and restrict the selection to EBAN, and EBKN tables.

      In this exercise, we will not fetch data from the rest of the tables.

    9. Choose the Data Filter and check the filters. Configure OBJECT_DISTRIBUTION_MODE filter = 1 OMDO filter (download data based on the filters in the config panel) set to TRUE.

      Filter = 2 – Dependency Queue (will ignore filters in config panel) do not configure initially.

      In the screenshot, the data Filter is highlighted.
    10. Expand the Data Segment and configure the following values:

      Data SegmentValue
      PREQ_ON_DEMAND

      PREQ_ITEMS=On

      PREQ_ACCOUNT_ASSGINMENT=On

      And the rest are Off.

      USER_LOCATION

      Plant= 1010

      Storage Location = 0001

      USER_RULE_ENABLEDX (set to True)
    11. Choose the Save button to save the changes.

    12. If requested, assign the configuration to a transport.

    13. Choose Continue to complete saving changes.

      Note

      Per the preceding configuration, only the Purchase Requisitions assigned to the Plant and Storage Location are downloaded. You can configure extra filters such as Created By (SY-UNAME) to restrict Purchase Requestions created by the current user.

Task 3: Perform the oMDO Model Configuration

This task involves the configuration of the oMDO Model. This includes creation of oData Model definition for entity type, entity set, association, association set, navigation property, and so on.

Steps

  1. Create the oMDO Model for your mobile application.

    Use the following data:

    FieldValue
    Entity Type NameZ_##_PurchaseRequisition
    Mobile ApplicationZIAM_##_ASSET_MANAGER
    oData Service IDZIAM_INVENTORY_MANAGER_##-0001 (** make sure you choose the Asset Manager Mobile App Service in the dropdown)
    oMDO IDZIAM150_##_PURCHASE_REQ (oMDO Object created in previous task)
    oMDO Entity TypePREQ
    Entity Set Name.Z_##_PurchaseRequisitions
    Creatable<flag>
    ActiveYes
    App Feature ID

    Z_CA_CORE_DATA_150

    For the training purpose we will reuse the Feature, but in a Project implementation, consider an appropriate feature or create a new one if required.

    1. Choose ConfigPanel Home.

    2. Choose oData Model Configuration in the oData Channel Integration Settings section.

    3. Once you are within the Mobile Application oData Mode Details, use the Mobile Application Filter dropdown to choose your Mobile Application IAM150-## (ZIAM_##_ASSET_MANAGER).

    4. Expand your application and choose Create and enter the data given in the table.

      Choose Create and enter the data from the table.
  2. Add the following properties to the oData Model.

    Use the following data:

    Property NameOMDO Field NameEdm TypeKey
    PurchasingReqBANFNEdm.StringX
    RequisnItemBNFPOEdm.StringX
    CreatedByERNAMEdm.String 
    DeliveryDateLFDATEdm.String 
    DeliveryDateCategoryLPEINEdm.String 
    DocCategoryBSTYPEdm.String 
    DocTypeBSARTEdm.String 
    ItemEBELPEdm.String 
    MaterialMATNREdm.String 
    PlantWERKSEdm.String 
    PriceUnitPEINHEdm.String 
    PurchGroupEKGRPEdm.String 
    PurchasngOrgEKORGEdm.String 
    QuantityMENGEEdm.Decimal (13,3) 
    RequisitionerAFNAMEdm.String 
    RequisnDateBADATEdm.String 
    ShortTextTXZ01Edm.String 
    StorageLocationLGORTEdm.String 
    UOMMEINSEdm.String 
    ValuationPricePREISEdm.Decimal (11.2) 

    1. Choose the Property List tab.

    2. Choose Add Property and add the properties as given in the properties table.

    3. Choose the Save button at the top of the screen to save your changes (use the same request you created previously).

  3. Repeat the steps to create Z_PurchaseReqAcctAsign.

    Use the following data:

    FieldValue
    Entity Type NameZ_##_PurchaseReqAcctAsign
    Mobile ApplicationZIAM_##_ASSET_MANAGER
    oData Service IDZIAM_##_INVENTORY_MANAGER-0001 (** make sure you choose the Asset Manager Mobile App Service in the dropdown)
    oMDO IDZIAM_##_PURCHASE_REQ (oMDO Object created in previous task)
    oMDO Entity TypePREQACCASGN
    Entity Set NameZZ_##_PurchaseReqAcctAsigns
    ActiveYes
    App Feature ID

    Z_CA_CORE_DATA_IAM150

    For the training purpose we will reuse the Feature, but in a Project implementation, consider an appropriate feature or create a new one if necessary.

    Add the following properties to the oData Model:

    Property NameoMDO Field NameEdm TypeKey
    PurchasingReqBANFNEdm.StringX
    RequisnItemBNFPOEdm.StringX
    SerNoAcctAssignZEBKNEdm.StringX
    CostCenterKOSTLEdm.String 
    GLAccountSAKTOEdm.String 
    OrderAUFNREdm.String 

    1. Perform the steps as described previously.

  4. Navigate back to Z_##_PurchaseRequisition to add Association and Navigation.

    Use the following data:

    FieldValueComments
    Principal EntityZ_##_PurchaseRequisition 
    Dependent EntityZ_##_PurchaseReqAcctAsign 
    Principal Cardinality1 
    Dependent Cardinality0..n 
    Association Set NamePurchaseRequisition_AccountAssignment_ASThis is automatically populated.
    Association NamePurchaseRequisition_AccountAssignmentThis is automatically populated.

    1. Perform the steps as described previously.

      In the screenshot, the Association & Set List tab is selected.
  5. Create Referential Constraints.

    Use the following data:

    Principal Entity TypePrincipal PropertyDependent Entity TypeDependent Type
    Z_##_PurchaseRequisitionPurchaseReqZ_##_PurchaseReqAcctAsignPurchaseReq
    Z_##_PurchaseRequisitionRequisnItemZ_##_PurchaseReqAcctAsignRequisnItem

    1. Perform the steps as previously described.

      The result should look like:In the screenshot, the Referential Constraints tab is selected.

  6. Create the navigate property to Z_##_PurchaseReqAcctAsign to add association and navigation.

    Use the following data:

    FieldValueComments
    AssociationPurchaseRequisition_AccountAssignmentUsing the dropdown menu, select the Association and the rest of the fields are automatically populated.
    Principal Entity NameZ_##_PurchaseRequisition 
    Target Entity NameZ_##_PurchaseReqAcctAsign 
    Navigation Property NameZ_##_PurchaseReqAcctAssign_Nav 
    Technical NameZ_##_PURCHASEREQACCTASSIGN_NAV 

    1. Perform the steps as previously described.

      The result looks like the following image:In the screenshot, the Navigation Property List tab is selected.

  7. Save your changes.

    1. Choose the Save button at the top of the screen to save your changes (use the same request you created previously).

Task 4: Perform Persona Assignment

This task involves the assignment of the oMDO → Feature and then Feature → User Persona.

Steps

  1. Assign oMDO to Feature.

    1. Log in to the SAP GUI.

    2. Enter /n/syclo/configpanel to launch the ConfigPane.

    3. Once you are within the Config Panel (Web Dynpro opens in Browser), choose Component Assignment in the General Info section.

    4. Once you are within the Application Assignment Configuration, choose your mobile application ZIAM_##_SERVICE_ASSET_MANAGER (IAM150-##).

    5. In the next screen, choose the oMOD Assignment tab.

    6. Choose the Change button.

    7. In the App Feature Id dropdown and select Z_CA_CORE_DATA_IAM150.

    8. In the oMDO ID dropdown and choose ZIAM_##_PURCHASE_REQ.

    9. In the filtered Assignment List table, choose the In-scope checkbox.

    10. Choose the Active checkbox to assign the oMDO to the feature.

  2. Assign Feature to Persona.

    In the previous task, we already assigned the feature to the Persona. However, if you created a new feature assign it to the Persona.

    1. Choose the User Personas tab.

    2. In the User Persona dropdown, choose INVENTORY_CLERK persona.

    3. In the App. Feature Id dropdown, choose Z_CA_CORE_DATA_IAM150.

    4. In the Feature Assignment table, choose the Activate checkbox to assign the feature to the persona.

    5. Choose the Save button to save your changes.

Task 5: Test Your Changes Using the Gateway Client

Steps

  1. Clear oData Service Cache for your service.

    1. Log in to SAP GUI.

    2. Enter the transaction code /N/IWFND/MAINT_SERVICE and choose Enter.

    3. Navigate to the service ZIAM_##_ASSET_MANAGER version 1.

      Note that the ZIAM_##_INVENTORY_MANAGER service is a subset of this composite service. The cache clean up of Asset Manager Service will automatically cascade to the subset.

      Note

      For additional information, check the oData Service Assignment in Config Panel to see how the services are assigned to your mobile applications and the composite settings.

    4. In the System Aliases section, choose the Service Implementation button.

    5. In the next screen, choose the Cleanup Cache button.

      A dialog box shows the message that the metadata has been reloaded.

    6. Back on the /IWFND/MAINT_SERVICE screen, choose the Load Metadata button.

  2. Test the Service in Gateway Client.

    1. In the /IWFND/MAINT_SERVICE screen navigate to the ICF Nodes section (at bottom left), choose the SAP Gateway Client to test the service using the Gateway Client.

      Note

      When you launch the Gateway Client (/IWFND/GW_CLIENT) via Maintain Service (/IWFND/MAINT_SERVICE) the Request URI is defaulted else you can enter /sap/opu/odata/sap/ZIAM_##_SAP_ASSET_MANAGER/?$format=xml

    2. Choose Execute to verify the service is working.

      Verify the ~status_code = 200.

    3. From the application toolbar, choose the EntitySets button.

    4. Choose Z_##_PurchaseRequisitions Entityset.

    5. The Request URI is updated to fetch the Z_##_PurchaseRequisitions Entityset/sap/opu/odata/sap/ZIAM_##_ASSET_MANAGER/Z_##_PurchaseRequisitions.

    6. Choose Execute.

    7. Repeat the steps for Z_##_PurchaseRequsitionsAcctAsgns.

      In the HTTP Response, verify that ~status_code = 200 and some data is returned in the response window.

      In the SAP Gateway Client, the response window is shown.
  3. Test from BTP Destination.

    Use: https://.../ /DEST_SAM2205_PPROP/Z_##_PurchaseRequisitions

    1. Perform the steps as described above, but now from the SAP BTP destination. The result is:

      Screenshot of the XML code.

      Note

      You can update the DEST_SAMxxxx_PPROP.ini file in BTP Offline Access feature to include Purchase Requisition in $batch

Download Purchase Requisition (Part-2: MDK Metadata)

Note

The steps below are giving a guide so that you can perform this exercise in your own system landscape.

Task 1: Enhance Inventory Overview Page to Display Purchase Requisitions

We enhance the Inventory Overview page of the Inventory Persona and to display the Purchase Requisition in a new tab.

Steps

  1. Copy the Overview Page from SAPAssetManager to the ZSAMComponent project and open it.

    1. Copy /SAPAssetManager/Pages/Inventory/InventoryOverview.pagetoto /ZSAMComponent/Pages/Inventory/InventoryOverview.page.

    2. Open the/ZSAMComponent/Pages/Inventory/InventoryOverview.page.

  2. Update the KPI Count to display the Purchase Requisitions.

    1. Search for the KPIItems section and add the following code after the Physical Inventory KPI count and before the Material Document Item Count.

      Note

      • Note that you must add a comma before and after the code insert.
      • We create the label and the rule for count later in this exercise.
      Code Snippet
      123456789
      { "MetricItems": [ { "Value": "/ZSAPComponent/Rules/Inventory/Overview/Z_PurchaseRequsitionKPIItemsCount.js" } ], "CaptionLabel": "$(L, z_purchaseRequisition_label)" },
  3. Add a code for a new tab to display Purchase Requisitions.

    Insert the following code after the Physical Inventory tab and before the Recent Tab section.

    1. Search for the Physical Inventory section and add the following code after the Physical Inventory tab and before the Recent tab section.

      Note

      • Note that you must add a comma before and after the code insert.
      • We create the label and the rule for List Page in the later in this exercise.
      Code Snippet
      1234567
      { "_Name": "Z_PurchaseRequisitionTab", "Caption": "$(L, z_purchaseRequisition_label)", "PageToOpen" : "/ZSAPComponent/Pages/Inventory/Z_PurchaseRequisition/Z_PurchaseRequisitionList.page", "_Type": "Control.Type.TabItem" },
  4. While in the Inventory Overview page, create the labels.

    1. Navigate to the code "CaptionLabel": "$(L, z_purchaseRequisition_label)"

      Hint

      You can use Ctrl+. to view the quick fixes option. Using the quick fix you can directly create an entry in the i18n without explicitly navigating to the file via explorer.

    2. Create an entry in i18n.properties (i18n_en.properties). The new entry will always be created at the end.

      Hint

      Keeping all your changes at the end of the file allows you to track the changes. Also helpful to migrate changes during upgrade.

Task 2: Create a Rule to Display the Count in KPI

Steps

  1. Create folders ZSAPComponent > Rules > Inventory > Overview.

    1. Perform the required steps as required in an earlier exercise.

  2. Create a new rule Z_PurchaseRequisitionKPIItemsCount.js with the following code:

    Code Snippet
    1234
    export default function Z_PurchaseRequisitionKPIItemsCount(context) { return context.count('/SAPAssetManager/Services/AssetManager.service', 'Z_##_PurchaseRequisitions', '').then((count) => { return count;}); }
    1. Perform the required steps as required in an earlier exercise.

Task 3: Create a List Page

Steps

  1. Create a folder ZSAPComponentPagesInventoryZ_PurchaseRequsition.

    1. Perform the required steps as required in an earlier exercise.

  2. Create a new in MDK Page with name Z_PurchaseRequisitionList.page.

    1. Right-click on ZSAPComponentPagesZ_PurchaseRequsition.

    2. Choose New MDK Page.

    3. In the Page creation wizard, select Section Page and choose Next.

    4. Enter the page name Z_PurchaseRequisitionList (without .page) and choose Next followed by Finish in the Confirmation window.

  3. Add Controls and configure the PurchaseRequisitionList page.

    Use the following data:

    FieldValue
    Service/ZSAMComponent/Services/AssetManager.service
    EntitySetZ_##_PurchaseRequisitions
    QueryOptions$orderby=PurchasingReq,RequisnItem

    1. Double-click on the newly created page PurchaseRequisitionList to open it in the layout editor (if not already open).

    2. Select the Controls tab.

    3. Enter the term Object Table in the search field and choose Enter.

    4. From the search results, drag the Object Table on to the PurchaseRequisitionList page.

    5. In the right pane Properties window, under the Target section use the dropdown and choose the values from the preceding table.

      Note

      If you have not synced the service before, do it now. Note that we only perform this on the AssetManager.service in ZSAMComponent. We will not change the standard SAPAssetManager project.

      In the Property tab, use the dropdown options to choose values.
  4. Update the properties in the Appearance section.

    Use the following data:

    PropertyValue
    CaptionPurchase Requisitions
    NameZ_PurchaseRequisitionList
    Description{ShortText}
    Subhead{ShortText}
    Title{PurchasingReq} - {RequisnItem}
    Footnote{Plant} {StoageLocation}
    StatusText{Quantity} {UOM}
    SubstatusText{ValuationPrice} {PriceUnit}
    1. Perform the required steps as described earlier.

Task 4: Update CIM File

Steps

  1. Add an entry in the CIM file for the InventoryOverview Page. The CIM is located in the SAPAssetManager project.

    1. Perform the required steps as described earlier. Use the following code:

      Code Snippet
      12345
      { "Source": "/ZSAPComponent/Pages/Inventory/InventoryOverview.page", "Target": "/SAPAssetManager/Pages/Inventory/InventoryOverview.page" }

Task 5: Deploy the App to SAP BTP (MDK Deploy) and Test

Steps

  1. Deploy the app to SAP BTP (MDK Deploy) and test.

    1. Right-click on the SAPAssetManagerApplication.app and choose the MDK:Deploy command from the context menu to deploy the mobile app.

      Screenshot showing the Purchase Requisitions tab.
    2. Perform some tests. To view the Purchase Requisitions, go to Profile SettingsSwitch PersonaChoose Inventory Clerk.

Task 6: Optional: Add Navigation to Account Assignment

  • Repeat the preceding steps to create another section page with object table control for displaying the Purchase Requisition Assignment.
  • Create a Navigation Action from Purchase Requisitions (onPress Event) to display the Account Assignment.

Create Purchase Requisition (Part 1: Back-end)

Note

Use the transaction SE24 and there the reference class handler /MERP/CL_MM_PURCHASE_REQ_OD to create your copy Zxxx files. The code snippets provided in this handbook are examples for your reference only. Copy the required coding from the reference class.

Note

The steps below are giving a guide so that you can perform this exercise in your own system landscape.

Task 1: Update the oMDO Class Handler: Development Tasks

Steps

  1. Update the oMDO Class for the previous created purchase requisition ZIAM_##_CL_MM_PURCHASE_REQ.

    1. Log in to the SAP system and navigate to transaction code SE24.

    2. Enter ZIAM_##_CL_MM_PURCHASE_REQ.

    3. Choose the Change button.

  2. Redefine the method /mfnd/if_core_omdo_handler-create with the following code:

    Code Snippet
    12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
    METHOD /mfnd/if_core_omdo_handler~create. super->create( CHANGING cref_omdo_data = cref_omdo_data ). REFRESH: tab_preq_items, tab_preq_item_texts, tab_preq_acc_assignment, tab_preq_header_text, tab_preq_limits, tab_preq_contract_limits, tab_preq_services, tab_preq_srv_accass_values, tab_preq_services_text, tab_preq_addrdelivery, tab_extensionin. TRY. LOOP AT cref_omdo_data->tab_omdo_entity_input ASSIGNING FIELD-SYMBOL(<entity_input>). CASE <entity_input>-tech_entity_type. WHEN const_preq_entity. convert_input_preq( EXPORTING iref_input_data = <entity_input>-request_data IMPORTING ev_error = DATA (ev_error ) ). WHEN const_preq_note_entity. convert_input_preq_notes( EXPORTING iref_input_data = <entity_input>-request_data IMPORTING ev_error = DATA(lv_error ) ). ENDCASE. IF ev_error = abap_true. RETURN. ENDIF. ENDLOOP. IF lv_error IS INITIAL. call_bapi_requisition_create( IMPORTING ev_banfn = DATA(lv_banfn_out) CHANGING cref_omdo_data = cref_omdo_data ). build_preq_output_data( EXPORTING iv_banfn = lv_banfn_out CHANGING cref_omdo_data = cref_omdo_data ). ENDIF. CATCH /merp/cx_core_exception_gen INTO DATA(lref_exception) ##CATCH_ALL. message = lref_exception->get_text( ). logger->logerror( iv_message = message iv_source = source iv_user_guid = user_guid iref_return_tab = cref_omdo_data->dref_return ). RETURN. ENDTRY. ENDMETHOD.
    1. Choose the Methods Tab.

    2. Choose Find and search for the method CREATE.

    3. Choose Redefine.

    4. Clear the code within the method and copy paste the given code into the method.

    5. Check the syntax with Ctrl + F2.

    6. Choose Save.

    7. Do not forget to activate the method by choosing Activate.

  3. Create the method CALL_BAPI_REQUISITION_CREATE with the following code:

    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
    METHOD call_bapi_requisition_create. CLEAR: ev_banfn. "Insert Start S4MERP SP11 bugid S4MOBADDON-2931 DATA: lv_skip_items_with_error TYPE bapimmpara-selection, lv_automatic_source TYPE bapimmpara-selection, ls_range TYPE /mfnd/core_range_str, lt_bapireturn TYPE STANDARD TABLE OF bapireturn, ls_return TYPE bapiret2, ls_thead TYPE thead. "oo Reference variables DATA: lref_exception TYPE REF TO cx_root. READ TABLE str_dof_filter_vals-skip_item_with_error->* INTO ls_range INDEX 1. IF sy-subrc = 0. lv_skip_items_with_error = ls_range-low. ENDIF. READ TABLE str_dof_filter_vals-automatic_source->* INTO ls_range INDEX 1. IF sy-subrc = 0. lv_automatic_source = ls_range-low. ENDIF. TRY. CALL FUNCTION 'BAPI_REQUISITION_CREATE' EXPORTING skip_items_with_error = lv_skip_items_with_error automatic_source = lv_automatic_source IMPORTING number = ev_banfn TABLES requisition_items = tab_preq_items requisition_account_assignment = tab_preq_acc_assignment requisition_item_text = tab_preq_item_texts requisition_limits = tab_preq_limits requisition_contract_limits = tab_preq_contract_limits requisition_services = tab_preq_services requisition_srv_accass_values = tab_preq_srv_accass_values return = lt_bapireturn requisition_services_text = tab_preq_services_text requisition_addrdelivery = tab_preq_addrdelivery extensionin = tab_extensionin. APPEND LINES OF lt_bapireturn TO cref_omdo_data->dref_return->*. LOOP AT lt_bapireturn ASSIGNING FIELD-SYMBOL() WHERE type = 'E' OR type = 'A'. APPEND TO cref_omdo_data->dref_return->*. CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. ENDLOOP. IF sy-subrc <> 0. CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = abap_true IMPORTING return = ls_return. ENDIF. CATCH /merp/cx_core_exception_gen INTO lref_exception. "#EC CATCH_ALL message = lref_exception->get_text( ). logger->logerror( iv_message = message iv_source = source iv_user_guid = user_guid iref_return_tab = cref_omdo_data->dref_return ). ENDTRY. ENDMETHOD.
    1. Perform the steps as described in the preceding step.

  4. Create the method BUILD_PREQ_OUTPUT_DATA with the following code:

    Code Snippet
    12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
    METHOD build_preq_output_data. FIELD-SYMBOLS: <data> TYPE any, <banfn> TYPE any, <bnfpo> TYPE any, <objkey> TYPE any, <textid> TYPE any. DATA: lt_preq TYPE gtyp_preq_key_tab, ls_preq TYPE gtyp_preq_key_str. IF iv_banfn IS NOT INITIAL. SELECT banfn bnfpo FROM eban INTO TABLE lt_preq WHERE banfn = iv_banfn. READ TABLE lt_preq INTO ls_preq INDEX 1. "#EC CI_NOORDER LOOP AT cref_omdo_data->tab_omdo_entity_input ASSIGNING FIELD-SYMBOL(). IF -tech_entity_type = const_preq_entity. READ TABLE lt_preq INTO ls_preq INDEX 1. "#EC CI_NOORDER IF sy-subrc = 0. ASSIGN -request_data->* TO . ASSIGN COMPONENT 'BANFN' OF STRUCTURE TO . CHECK sy-subrc = 0. ASSIGN COMPONENT 'BNFPO' OF STRUCTURE TO . CHECK sy-subrc = 0. <banfn> = ls_preq-banfn. <bnfpo> = ls_preq-bnfpo. DELETE lt_preq INDEX 1. "#EC CI_NOORDER ENDIF. ENDIF. IF <entity_input>-tech_entity_type = const_preq_note_entity. IF ls_preq-banfn IS NOT INITIAL. ASSIGN <entity_input>-request_data->* TO <data>. ASSIGN COMPONENT 'BANFN' OF STRUCTURE <data> TO <banfn>. CHECK sy-subrc = 0. ASSIGN COMPONENT 'OBJKEY' OF STRUCTURE <data> TO <objkey>. CHECK sy-subrc = 0. ASSIGN COMPONENT 'TEXT_ID' OF STRUCTURE <data> TO <textid>. CHECK sy-subrc = 0. <banfn> = ls_preq-banfn. <textid> = 'B01'. CONCATENATE ls_preq-banfn ls_preq-bnfpo INTO <objkey>. ENDIF. ENDIF. cref_omdo_data->add_omdo_output_single( iv_tech_entity_type = <entity_input>-tech_entity_type iv_request_no = <entity_input>-request_no iref_data = <entity_input>-request_data ). ENDLOOP. ENDIF. ENDMETHOD. "#EC CI_CYCLO
    1. Perform the steps as described in Step 2.

Create Purchase Requisition (Part-2: MDK Metadata)

Note

The steps below are giving a guide so that you can perform this exercise in your own system landscape.

Task 1: Enhance the Inventory Overview Page to Create Purchase Requisitions

In this task, we enhance the Inventory Overview page to add an action for creating the Purchase Requisition.

Steps

  1. Open the ZSAMComponent Inventory Overview page.

    1. In the Explorer view, navigate to the ZSAMComponent Inventory Overview page.

    2. Right click and from the menu choose Open WithCode Editor/ZSAPComponent/Pages/Inventory/InventoryOverview.page.

  2. In the ActionBar section and change the onPress code form SAPAssetManager to ZSAPComponent.

    1. In the Code Editor view page, navigate to the ActionBar section and change the code as shown after this:

      From:

      Code Snippet
      123
      "OnPress": "/SAPAssetManager/Actions/Inventory/CreateUpdateDelete/CreateDocumentPopover.action"
      to
      Code Snippet
      12
      "OnPress": "/ZSAPComponent/Actions/Inventory/CreateUpdateDelete/CreateDocumentPopover.action"

Task 2: Enhance the Action for Triggering Create Purchase Requisition

Steps

  1. Create the folder /ZSAPComponent/Actions/Inventory/CreateUpdateDelete.

    1. Create a folder as described in earlier exercises.

  2. Copy the file CreateDocumentPopover.action from /SAPAssetManager/Actions/Inventory/CreateUpdateDelete to / /ZSAPComponent/Actions/Inventory/CreateUpdateDelete/.

    1. The copy procedure is described in an earlier exercise.

  3. Extend CreateDocumentPopover.action.

    1. Right-click and open the CreateDocumentPopover.action in the Code Editor.

    2. Add the following code to after the Physical Inventory creation action.

      Code Snippet
      12345
      { "Title": "$(L, z_add_purchase_requisition)", "OnPress": "/ZSAPComponent/Rules/Inventory/Z_PurchaseRequisition/SetPurchaseRequisitionCreate.js" }
  4. Create an entry in the i18n.properties for the Z_add_purchase_requisition.

    1. Place the cursor on the Z_add_purchase_requisition and simultaneously choose the two keys: Ctrl and the Period (.) (in the following displayed as Ctrl +.).

    2. Choose MDK: Create i18n entry for key: z_add_purchase_requisition and add the text Add Purchase Requisition.

Task 3: Create a Rule and Action to Navigate to the Purchase Requisition Create Page

Steps

  1. Create the rule SetPurchaseRequisitionCreate.js.

    1. Place the cursor on the SetPurchaseRequisitionCreate.js and use Ctrl +. to create the rule.

    2. Open the rule and add the following code:

      Code Snippet
      1234567891011121314151617
      import libCom from '../../../../SAPAssetManager/Rules/Common/Library/CommonLibrary'; /** * Describe this function... * @param {IClientAPI} context */ export default function SetPurchaseRequisitionCreate(context) { libCom.setStateVariable(context, 'Temp_PurchaseReqReadLink',''); libCom.setStateVariable(context, 'Z_PurchaseRequisitionReturnToList', true); libCom.setStateVariable(context, 'Local_PurchaseReq',''); libCom.setStateVariable(context, 'PhysicalInventoryLocalFiscalYear', new Date().getFullYear().toString()); //Navigate Action to create page return context.executeAction('/ZSAPComponent/Actions/Inventory/Z_PurchaseRequisition/Z_PurchaseRequisitionCreateNav.action'); }
  2. Create the action Z_PurchaseRequisitionCreateNav.action.

    1. While in the SetPurchaseRequisitionCreate.js Rule, place cursor on the Z_PurchaseRequisitionCreateNav.action and use Ctrl +. to create a Navigation Action.

      This will also create a new folder in the Actions.

    2. Right click on the Z_PurchaseRequisitionCreateNav.action and open in Code Editor and enter the following code:

      Note

      The statement ModalPage opens the new Page as a model.

      Code Snippet
      123456
      { "_Type": "Action.Type.Navigation", "PageToOpen": "/ZSAPComponent/Pages/Inventory/Z_PurchaseRequisition/Z_PurchaseRequisitionCreate.page", "ModalPage": true }

Task 4: Create the Purchase Requisition Create Page

Steps

  1. Create the MDK Page Z_PurchaseRequisitionCreate.page.

    1. While in the Z_PurchaseRequisitionCreateNav.action, place the cursor on the Z_PurchaseRequisitionCreate.page and use Ctrl +. to create a Section MDK Page.

    2. When prompted to choose Page Type, choose the Section Page.

    3. Right click and open the page in Code Editor and insert the following code.

      Code Snippet
      123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
      { "Caption": "$(L,z_PurchaseRequisitionCreate)", "ActionBar": { "Items": [ { "Position": "left", "SystemItem": "Cancel", "OnPress": "/SAPAssetManager/Rules/Common/CheckForChangesBeforeClose.js" }, { "Position": "right", "SystemItem": "$(PLT,'Done','')", "Text": "$(L,apply)", "OnPress": "/ZSAPComponent/Actions/Inventory/Z_PurchaseRequisition/Z_PurchaseRequisitionCreate.action" } ] }, "Controls": [ { "Sections": [ { "Controls": [ { "_Name": "PurchasingReq", "Caption": "$(L,z_purchaseRequisitionID)", "_Type": "Control.Type.FormCell.SimpleProperty", "IsEditable": false, "Value": "%000000001" }, { "_Name": "RequisnItem", "Caption": "$(L,z_purchaseRequisitionItem)", "_Type": "Control.Type.FormCell.SimpleProperty", "IsEditable": true, "Value": "{RequisnItem}", "KeyboardType": "Number" }, { "IsEditable": true, "Value": "{ShortText}", "KeyboardType": "Number", "_Name": "ShortText", "Caption": "$(L,z_ShortText)", "_Type": "Control.Type.FormCell.SimpleProperty" } ] }, { "Controls": [ { "_Name": "PlantLstPkr", "_Type": "Control.Type.FormCell.ListPicker", "Caption": "$(L,plant)", "AllowMultipleSelection": false, "AllowDefaultValueIfOneItem": false, "IsPickerDismissedOnSelection": true, "IsSearchCancelledAfterSelection": true, "Search": { "Enabled": true, "Delay": 500, "MinimumCharacterThreshold": 3, "Placeholder": "$(L,search)", "BarcodeScanner": true }, "IsEditable": true, "PickerItems": { "DisplayValue": "{{#Property:Plant}} - {{#Property:PlantDescription}}", "ReturnValue": "{Plant}", "Target": { "EntitySet": "Plants", "Service": "/SAPAssetManager/Services/AssetManager.service", "QueryOptions": "$orderby=Plant asc" } } }, { "_Name": "StorageLocationPicker", "_Type": "Control.Type.FormCell.ListPicker", "Caption": "$(L,storage_location)", "AllowEmptySelection": true, "AllowMultipleSelection": false, "IsPickerDismissedOnSelection": true, "AllowDefaultValueIfOneItem": true, "Value": "{StorageLocation}", "IsEditable": true, "IsSelectedSectionEnabled": false, "PickerItems": { "DisplayValue": "{{#Property:StorageLocation}} - {{#Property:StorageLocationDesc}}", "ReturnValue": "{StorageLocation}", "Target": { "EntitySet": "StorageLocations", "QueryOptions": "$orderby=Plant asc", "Service": "/SAPAssetManager/Services/AssetManager.service" } }, "PickerPrompt": "$(L,select_single_item)" }, { "_Name": "MatrialListPicker", "_Type": "Control.Type.FormCell.ListPicker", "Caption": "$(L,material_number)", "AllowMultipleSelection": false, "AllowDefaultValueIfOneItem": true, "IsPickerDismissedOnSelection": true, "IsSearchCancelledAfterSelection": true, "Search": { "Enabled": true, "Delay": 500, "MinimumCharacterThreshold": 1, "Placeholder": "$(L,search)", "BarcodeScanner": true }, "Value": "{Material}", "IsEditable": true, "PickerItems": { "ObjectCell": { "PreserveIconStackSpacing": false, "Title": "{{#Property:MaterialNum}} - {{#Property:Description}}" //"Subhead": "{Plant}" //"Footnote": "{StorageLocation} - {StorageLocationDesc}", }, "ReturnValue": "{MaterialNum}", "Target": { "EntitySet" : "Materials", //"EntitySet": "MaterialSLocs", "Service" : "/SAPAssetManager/Services/AssetManager.service", "QueryOptions" : "$orderby=MaterialNum" } } }, { "_Name": "PurchasngOrgPkr", "_Type": "Control.Type.FormCell.ListPicker", "Caption": "$(L,z_PurchasngOrg)", "AllowMultipleSelection": false, "AllowDefaultValueIfOneItem": false, "IsPickerDismissedOnSelection": true, "IsSearchCancelledAfterSelection": true, "Search": { "Enabled": true, "Delay": 500, "MinimumCharacterThreshold": 3, "Placeholder": "$(L,search)", "BarcodeScanner": true }, "IsEditable": true, "PickerItems": { "DisplayValue": "{{#Property:PurchasingOrg}} - {{#Property:PlantDescription}}", "ReturnValue": "{PurchasingOrg}", "Target": { "EntitySet": "Z_##_PurchaseOrganizations", "Service": "/ZSAPComponent/Services/AssetManager.service", "QueryOptions": "$orderby=PurchasingOrg asc" } } }, { "_Name": "PurchGroup", "Caption": "$(L,z_PurchGroup)", "Value": "001", "IsEditable": true, "IsVisible": true, "_Type": "Control.Type.FormCell.SimpleProperty" }, { "_Name": "Quantity", "Caption": "$(L,quantity)", "IsEditable": true, "KeyboardType": "Number", "Value": "{Quantity}", "_Type": "Control.Type.FormCell.SimpleProperty" }, { "_Name": "UOMListPicker", "_Type": "Control.Type.FormCell.ListPicker", "Caption": "$(L,uom)", "AllowMultipleSelection": false, "AllowDefaultValueIfOneItem": true, "IsPickerDismissedOnSelection": true, "IsSearchCancelledAfterSelection": true, "Search": { "Enabled": true, "Delay": 500, "MinimumCharacterThreshold": 1, "Placeholder": "$(L,search)", "BarcodeScanner": true }, "Value": "{UOM}", "IsEditable": false, "PickerItems": { "ReturnValue": "{BaseUOM}", "DisplayValue": "{BaseUOM}", "Target": { "EntitySet" : "MaterialUOMs", "Service" : "/SAPAssetManager/Services/AssetManager.service", "QueryOptions": "$orderby=UOM" } } } ] }, { "Controls": [ { "_Name": "DeliveryDatePicker", "Caption": "$(L,z_DeliveryDate)", "_Type": "Control.Type.FormCell.DatePicker", "DateTimeEntryMode" : "date", "Mode" : "Date", "Value": "{DeliveryDate}", "IsEditable": false }, { "_Name": "DeliveryDateCategory", "Value": "1", "IsEditable": false, "IsVisible": false, "_Type": "Control.Type.FormCell.SimpleProperty" }, { "_Name": "DocCategory", "Caption": "$(L,z_DocCategory)", "Value": "B", "IsEditable": false, "IsVisible": true, "_Type": "Control.Type.FormCell.SimpleProperty" }, { "_Name": "DocType", "Caption": "$(L,z_DocType)", "Value": "NB", "IsEditable": false, "IsVisible": true, "_Type": "Control.Type.FormCell.SimpleProperty" }, { "_Name": "PriceUnit", "Value": "1", "IsEditable": false, "IsVisible": true, "_Type": "Control.Type.FormCell.SimpleProperty" }, { "_Name": "ValuationPrice", "Caption": "$(L,z_ValuationPrice)", "Value": "{ValuationPrice}", "IsEditable": true, "IsVisible": true, "_Type": "Control.Type.FormCell.SimpleProperty", "AlternateInput": "Barcode" } ] } ], "_Name": "FormCellContainer", "_Type": "Control.Type.FormCellContainer" } ], "_Type": "Page", "Name": "Z_PurchaseRequisitionCreate", "PrefersLargeCaption": true, "OnReturning": "/SAPAssetManager/Rules/Inventory/PhysicalInventory/Count/PhysicalInventoryCountUpdateOnReturning.js" }
  2. Create the following text strings/labels in i18n.properties:

    Entry
    z_purchaseRequistion_label=Purchase Requisitions
    z_add_purchase_requisition=Add Purchase Requisition
    z_PurchaseRequisitionCreate=Create Purchase Requisition
    z_purchaseRequisitionID=Purchase Requisition
    z_purchaseRequisitionItem=Item
    z_ShortText=Short Text
    z_PurchasngOrg=Purchase organization
    z_PurchGroup=Purchase Group
    z_DeliveryDate=Delivery Date
    z_DocCategory=Document Category
    z_DocType=Document Type
    z_ValuationPrice=Price
    1. Perform the required steps as described in previous exercises.

Task 5: Create OnPress Action to Check for Required Field

Steps

  1. Use the code to create a check for the required field.

    1. While in the Z_PurchaseRequisitionCreate.page navigate to the OnPress Action. This is the code:

      Code Snippet
      12
      "OnPress": "/ZSAPComponent/Actions/Inventory/Z_PurchaseRequisition/Z_PurchaseRequisitionCreateRequired.action"
    2. Place the cursor on the action and use Ctrl +. to create the action for checking the required fields.

    3. Use the following code:

      Code Snippet
      123456789101112131415161718192021
      { "OnFailure": "/SAPAssetManager/Rules/Common/UpdateRequiredFailed.js", "OnSuccess": "/ZSAPComponent/Rules/Inventory/Z_PurchaseRequisition/Z_PurchaseRequisitionCreateOnCommit.js", "RequiredFields": [ "PurchasingReq", "RequisnItem", "ShortText", "MatrialListPicker", "PlantLstPkr", "Quantity", "ValuationPrice", "DocCategory", "DocType" ], "_Type": "Action.Type.CheckRequiredFields", "ShowActivityIndicator": true, "ActivityIndicatorText" : " " }

Task 6: Create Z_PurchaseRequisitionCreateOnCommit Rule to Validate the Fields and Call Commit Action

Steps

  1. Create a Z_PurchaseRequisitionCreateOnCommit rule to validate the fields and call the commit action.

    1. Use the following code:

      Code Snippet
      123456789101112131415161718192021222324252627282930
      import commonLib from '../../../../SAPAssetManager/Rules/Common/Library/CommonLibrary'; import Logger from '../../../../SAPAssetManager/Rules/Log/Logger'; export default function Z_PurchaseRequisitionCreateOnCommit(context) { let onCreate = commonLib.IsOnCreate(context); return validateData(context).then(valid => { if (valid) { if (onCreate) { let plant = context.getPageProxy().getControl('FormCellContainer').getControl('PlantLstPkr').getValue()[0].ReturnValue; commonLib.setStateVariable(context, 'Z_PurchaseRequisitionPlant', plant); let storageLocation = context.getPageProxy().getControl('FormCellContainer').getControl('StorageLocationPicker').getValue()[0].ReturnValue; commonLib.setStateVariable(context, 'Z_PurchaseRequisitionStorageLocation', storageLocation); return context.executeAction('/ZSAPComponent/Actions/Inventory/Z_PurchaseRequisition/Z_PurchaseRequisitionCreate.action').then(() => { return context.executeAction('/SAPAssetManager/Actions/Page/ClosePage.action'); }).catch((error)=>{ Logger.error('PurchaseRequisition', 'PurchaseRequisition.create error: ${error}'); }); } else { //Update NOT Supported } } return false; //Validation failed }) }

Task 7: Create the Purchase Requisition Action

Screenshot of the purchase requisition action.

Steps

  1. Create the Purchase Requisition Action.

    1. Use the following code:

      Code Snippet
      12345678910111213141516171819202122232425262728293031323334
      { "_Type": "Action.Type.ODataService.CreateEntity", "ShowActivityIndicator": true, "Target": { "Service": "/ZSAPComponent/Services/AssetManager.service", "EntitySet": "Z_##_PurchaseRequisitions" }, "Properties": { "PurchasingReq": "#Control:PurchasingReq/#Value", "RequisnItem": "#Control:RequisnItem/#Value", "CreatedBy": "/SAPAssetManager/Rules/MobileStatus/GetSAPUserId.js", "DeliveryDate": "#Control:DeliveryDatePicker/#Value", "DeliveryDateCategory": "#Control:DeliveryDateCategory/#Value", "DocCategory": "#Control:DocCategory/#Value", "DocType": "#Control:DocType/#Value", "Material": "#Control:MatrialListPicker/#SelectedValue", "Plant": "#Control:PlantLstPkr/#SelectedValue", "PriceUnit": "#Control:PriceUnit/#Value", "PurchGroup": "#Control:PurchGroup/#Value", "PurchasngOrg": "#Control:PurchasngOrgPkr/#SelectedValue", "Quantity": "#Control:Quantity/#Value", "RequisnDate": "#Control:DeliveryDatePicker/#Value", "ShortText": "#Control:ShortText/#Value", "StorageLocation": "#Control:StorageLocationPicker/#SelectedValue", "UOM": "#Control:UOMListPicker/#SelectedValue", "ValuationPrice": "#Control:ValuationPrice/#Value" }, "Headers": { "OfflineOData.RemoveAfterUpload": "true", "OfflineOData.TransactionID": "%000000001" } }

Task 8: Deploy the App to BTP (MDK Deploy) and Test

Steps

  1. Deploy the app to SAP BTP (MDK Deploy) and test.

    1. Right-click on the SAPAssetManagerApplication.app and from the context menu choose MDK:Deploy to deploy the Mobile App.

      Choose the plus icon, then select Add Purchase Requisition.

Log in to track your progress & complete quizzes