|
| 1 | +--- |
| 2 | +parser: v2 |
| 3 | +auto_validation: true |
| 4 | +primary_tag: products>sap-btp--abap-environment |
| 5 | +tags: [ tutorial>Intermediate, topic>abap-development, SBPA Workflows software-product>sap-business-technology-platform, tutorial>licensen] |
| 6 | +time: 30 mins |
| 7 | +author_name: Ruchi Dobriyal |
| 8 | +author_profile: https://github.com/RDobriyal |
| 9 | +--- |
| 10 | + |
| 11 | +# Extend the RAP Travel Application to integrate workflow capability |
| 12 | +<!-- description --> Enhance the business object behavior using determination to add workflow functionality. |
| 13 | + |
| 14 | +## You will learn |
| 15 | +- How to define determinations |
| 16 | +- How to implement determination |
| 17 | +- How to use EML in Local Mode |
| 18 | + |
| 19 | + |
| 20 | +## Prerequisites |
| 21 | +- You need to have access to an SAP BTP, ABAP environment, or SAP S/4HANA Cloud, ABAP environment or SAP S/4HANA (release 2022 or higher) system. |
| 22 | +- Latest Version of ADT with [abapGit plugin](https://eclipse.abapgit.org/updatesite/) |
| 23 | +- You have created the Travel App with workflow handler class as explained [here](https://developers-qa-blue.wcms-nonprod.c.eu-de-2.cloud.sap/tutorials/abap-environment-sbpa-workflow-handler-class.html#449f0c32-02ac-44f1-9036-f969a8d553c6) |
| 24 | + |
| 25 | +## Intro |
| 26 | +As part of this tutorial, you would extend the Managed Business Object behaviour by defining and implementing a **Determination on Save** `trigger_travelworkflow` during action **Create** (trigger condition). You will use the Entity Manipulation Language *to implement the transactional behavior of the Travel business object*. |
| 27 | + |
| 28 | +On **Creation** of the travel booking, during save event Determination on Save `trigger_travelworkflow` will be called. `trigger_travelworkflow` will intern **trigger workflow** for travel approval and set the overall status of the travel to **awaiting approval.** |
| 29 | + |
| 30 | +*Reminder: Do not forget to replace the suffix placeholder #### with your chosen or assigned group ID in the exercise steps below.* |
| 31 | + |
| 32 | +>A determination is an optional part of the business object behavior that modifies instances of business objects based on trigger conditions. Determinations are implemented when we need to calculate values of few fields based on trigger conditions. |
| 33 | +
|
| 34 | +>A determination is implicitly invoked by the RAP framework if the trigger condition of the determination is fulfilled. Trigger conditions can be CRUD operations or fields. Determinations can be created On modify or On save based on if we want to display the value of a calculated field to the user before save or after save. |
| 35 | +
|
| 36 | +>Please refrain from writing fields which needs to be determined / calculated in the trigger conditions of that determination as it might lead to infinite loop since we are specifying the calculated field in the trigger condition and changing the field inside that determination which is resulting in application dumps. |
| 37 | +
|
| 38 | +### Define Determination. |
| 39 | + |
| 40 | +**Extend** the Business Object Behaviour definition with **Determination On Save**. |
| 41 | + |
| 42 | +1. Go to behaviour definition of the Travel root entity  `ZR_RAP_TRAVEL_####` and define the determination `trigger_travelworkflow`. For that, insert the following code as shown in the screenshot below. |
| 43 | + |
| 44 | +```ABAP Code |
| 45 | +
|
| 46 | + determination trigger_travelworkflow on save `{create;}` |
| 47 | +
|
| 48 | +``` |
| 49 | + |
| 50 | +  |
| 51 | + |
| 52 | + **Short explanation:** This statement specifies that the determination would be triggered during the save event of the operation Create. The determined values would be visible after save. |
| 53 | + |
| 54 | + 2. **Activate**  the changes |
| 55 | + |
| 56 | + 3. **Click** on the **Quick Assist**  besides the newly added line of code and the **Add method for determination** to declare the required method in behavior implementation class. |
| 57 | + |
| 58 | +  |
| 59 | + |
| 60 | + 4. As a result, you can see the method `trigger_travelworkflow` for determination is added in the local handler class LHC_TRAVEL of Behaviour implementation class `ZBP_R_RAP_TRAVEL_RD02` |
| 61 | + |
| 62 | +  |
| 63 | + |
| 64 | + **Short Explanation:** |
| 65 | + |
| 66 | + - The addition **FOR DETERMINE** indicates that the method provides the implementation of a determination and the addition **ON SAVE** indicates the **specified trigger time** (during save event). |
| 67 | + |
| 68 | + - **IMPORTING** parameter **keys** – is an internal table containing the **keys of the instances** the determination will be executed on. Includes all entities for which keys must be assigned. |
| 69 | + |
| 70 | + - Implicit CHANGING parameter **reported** - used to return messages in case of failure. |
| 71 | + |
| 72 | + 5. Activate  the changes |
| 73 | + |
| 74 | +### Implement Determination |
| 75 | + |
| 76 | +You will now implement the determination to call trigger workflow method created as part of the previous tutorial and update the overall status of Travel to **(W)** Awaiting Approval using **(EML)** Entity Manipulation Language In **Local Mode**. |
| 77 | + |
| 78 | +>Calling EML statements in the local mode - by using the addition IN LOCAL MODE –excludes feature controls and authorization checks. This addition can thus be used to change a BO Instance locally by the same RAP business object itself, i. e. not for other RAP business objects. |
| 79 | +
|
| 80 | + 1. Define the **local constant** `travel_status` to store the allowed value of the **overall status** of a Travel instance. Insert the following code snippet in the definition part of the local handler class `lhc_travel` in **Private section** as shown on the screenshot below. |
| 81 | + |
| 82 | + Insert the following code snippet. |
| 83 | + |
| 84 | + ```ABAP Code: |
| 85 | + CONSTANTS |
| 86 | + "Travel Status: |
| 87 | + BEGIN OF travel_status |
| 88 | + open TYPE c Length 1 Value 'O', "Open |
| 89 | + accepted TYPE c Length 1 Value 'A', "Accepted |
| 90 | + rejected TYPE c Length 1 Value 'R', "Rejected |
| 91 | + waiting TYPE c Length 1 Value 'W', "Awaiting Approval |
| 92 | + End of travel_status |
| 93 | + ``` |
| 94 | + |
| 95 | + Your code should look like |
| 96 | + |
| 97 | +  |
| 98 | + |
| 99 | + 2. Implement the method `trigger_travelworkflow` in the local class `lhc_travel` of the Business Object Behaviour Implementation Class `ZBP_R_RAP_TRAVEL_####`. |
| 100 | + |
| 101 | + Insert the following code snippet in the method and replace all occurrences of the placeholder `####` with your group ID. You can use the F1 help to get detailed information on each EML statement |
| 102 | + |
| 103 | + |
| 104 | + ```ABAP Code: |
| 105 | + METHOD trigger_travelworkflow. |
| 106 | + |
| 107 | + IF keys IS NOT INITIAL. |
| 108 | + |
| 109 | + READ ENTITIES OF ZR_RAP_Travel_RD02 IN LOCAL MODE |
| 110 | + ENTITY travel |
| 111 | + ALL FIELDS |
| 112 | + WITH CORRESPONDING #( keys ) |
| 113 | + RESULT DATA(travels). |
| 114 | + |
| 115 | + data(ls_travel) = travels[ 1 ]. |
| 116 | + |
| 117 | + SELECT SINGLE name FROM /DMO/I_Agency WHERE AgencyID = @ls_travel-AgencyID |
| 118 | + INTO @DATA(agency_name). |
| 119 | + |
| 120 | + SELECT SINGLE firstname, lastname, title FROM /DMO/I_Customer |
| 121 | + WHERE CustomerID = @ls_travel-customerID |
| 122 | + INTO ( @DATA(firstname), @DATA(lastname), @DATA(title) ). |
| 123 | + |
| 124 | + IF sy-subrc = 0. |
| 125 | + |
| 126 | + CONCATENATE title firstname lastname INTO DATA(Customer_name) SEPARATED BY space. |
| 127 | + |
| 128 | + |
| 129 | + NEW zcl_r_rap_workflow_rd02( )->trigger_workflow( |
| 130 | + travelid = ls_travel-travelid |
| 131 | + agency_name = agency_name |
| 132 | + booking_fee = ls_travel-bookingfee |
| 133 | + Currency_code = ls_travel-currencycode |
| 134 | + Customer_name = Customer_name |
| 135 | + Total_price = ls_travel-Totalprice |
| 136 | + ). |
| 137 | + |
| 138 | + " Replace the suffix with your choosen group id. |
| 139 | + "This is done to update the Overall Travel Status to Awaiting Approval. |
| 140 | + MODIFY ENTITIES OF ZR_RAP_TRAVEL_RD02 IN LOCAL MODE |
| 141 | + ENTITY travel |
| 142 | + UPDATE FIELDS ( OverallStatus ) |
| 143 | + WITH VALUE #( FOR key IN keys ( %tky = key-%tky |
| 144 | + OverallStatus = travel_status-waiting ) ) |
| 145 | + FAILED DATA(ls_failed) |
| 146 | + REPORTED DATA(ls_reported). |
| 147 | + ENDIF. |
| 148 | + ENDIF. |
| 149 | + ENDMETHOD. |
| 150 | + ``` |
| 151 | + |
| 152 | + your code should look like |
| 153 | + |
| 154 | +  |
| 155 | + |
| 156 | + **Short Explanation** |
| 157 | + |
| 158 | + - **Read** the travel instance(s) data with the transferred keys (**keys**) using the EML statement **READ ENTITIES IN Local MODE**. |
| 159 | + - **Enrich** the data by getting Agency Name and Customer name, by reading from the CDS Views. |
| 160 | + - **Call** the method **trigger_workflow** from workflow handler class **zcl_r_rap_workflow_####** to **trigger workflow** by passing all the required data retrieved in the previous steps. |
| 161 | + - As a final step update the **Overall Travel Status** to `Awaiting Approval` by EML statement MODIFY ENTITIES `IN Local Mode` using the transferred keys (keys). |
| 162 | + |
| 163 | + 3. **Activate**  the changes |
| 164 | + |
| 165 | + >**Where** to trigger the workflow from, in case of **Unmanaged Numbering?** |
| 166 | + The actions required to trigger a workflow instance are defined as save actions and can thus only be called during the **early or late save phase** of a RAP Business Object. |
| 167 | + Choosing between early or late phase totally depends on how you are generating the numbering for the key field like in this case **Travel ID**. As the key would be required for your identifying the entry during callback processing. |
| 168 | + |
| 169 | + >**Early Numbering:** Trigger the workflow instance in a determination on save with the required methods. |
| 170 | + |
| 171 | + >**Late Numbering:** Trigger the workflow in a determination on save. To get the generated key field , you can set the payload with the setPayload method even later in the adjust_numbers method. |
| 172 | + |
| 173 | +### Add Value Help to enrich Travel Application UI. |
| 174 | + |
| 175 | +Without proper values for Customer ID and Agency ID the read on the CDS views to get Customer Name and Agency Name would not work. Thus, add value help to the fields to select values. |
| 176 | + |
| 177 | + 1. Go to metadata extensions for your RAP application |
| 178 | + |
| 179 | +  |
| 180 | + |
| 181 | + 2. Using the below annotation add value help for Agency ID. |
| 182 | + Insert this code above the field name AgencyID in Metadata Extension. |
| 183 | + |
| 184 | + ```ABAP Code: |
| 185 | + @Consumption.valueHelpDefinition: |
| 186 | + [{entity: { name: ' /DMO/I_Agency_StdVH', |
| 187 | + element: ' AgencyID' }}]` |
| 188 | + ``` |
| 189 | +
|
| 190 | + 3. Using the below annotation add value help for Customer ID. |
| 191 | + Insert this code above the field name CustomerID in Metadata Extension. |
| 192 | +
|
| 193 | + ```ABAP Code: |
| 194 | + @Consumption.valueHelpDefinition: |
| 195 | + [{entity: { name: '/DMO/I_Customer_StdVH', |
| 196 | + element: 'CustomerID' }}] |
| 197 | + ``` |
| 198 | + |
| 199 | + **Short explanation:** Here entity name is the Value help CDS View for field and element name in the corresponding field name in Value Help CDS View for which the Value help is being provisioned. |
| 200 | +
|
| 201 | + **Value Help** should now be **available** for the fields. |
| 202 | +
|
| 203 | + With this you are done with the implementation part, further we will see how to Preview, run, monitor, and troubleshoot the Travel App. |
| 204 | +
|
| 205 | + >In case your value help shows no data try to clear your browser cache or try previewing the application with browser in Inprivate or Incognito mode. |
| 206 | +
|
| 207 | +### Test yourself |
| 208 | +
|
| 209 | +
|
| 210 | +
|
| 211 | + |
| 212 | + |
| 213 | +
|
| 214 | +
|
| 215 | +
|
| 216 | +
|
| 217 | +
|
| 218 | +
|
| 219 | + |
| 220 | + |
0 commit comments