https://raw.githubusercontent.com/ajmaradiaga/feeds/main/scmt/topics/SAP-S4HANA-Cloud-ABAP-Environment-blog-posts.xml SAP Community - SAP S/4HANA Cloud ABAP Environment 2026-03-04T09:01:23.158667+00:00 python-feedgen SAP S/4HANA Cloud ABAP Environment blog posts in SAP Community https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-sap/using-custom-logic-in-sap-s-4hana-cloud-to-restrict-multiple-parkings-of/ba-p/14273192 Using Custom Logic in SAP S/4HANA Cloud to restrict multiple parkings of supplier invoices 2025-11-20T04:38:24.793000+01:00 Zhehui_Xia28 https://community.sap.com/t5/user/viewprofilepage/user-id/40727 <H2 id="toc-hId-1765539711">Problem Background:</H2><P>A customer has requested a requirement to restrict the repeated parking of goods receipt reference documents and reference document items corresponding to purchase orders that have already been parked and posted. If a purchase order has already completed goods receipt, reference document, and invoice posting, it should no longer be possible to park an invoice for this purchase order.</P><H2 id="toc-hId-1569026206">Solution:</H2><P>Attempt to meet the requirement through custom logic using a BAdI.</P><H2 id="toc-hId-1372512701">Analysis Steps:</H2><P>1. We have previously assisted customers with invoicing requirements, and the business enhancement points we need to use are the same. You can refer to these two blogs:&nbsp;<A href="https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-sap/%E5%9C%A8-sap-s-4hana-cloud-%E4%B8%AD%E9%80%9A%E8%BF%87%E8%87%AA%E5%AE%9A%E4%B9%89%E9%80%BB%E8%BE%91%E6%A3%80%E6%9F%A5%E9%A2%84%E5%88%B6%E5%8F%91%E7%A5%A8%E7%9A%84%E4%BB%98%E6%AC%BE%E6%9D%A1%E4%BB%B6%E4%B8%8E%E4%BE%9B%E5%BA%94%E5%95%86%E4%B8%BB%E6%95%B0%E6%8D%AE%E4%B8%AD%E7%9A%84%E4%BB%98%E6%AC%BE%E6%9D%A1%E4%BB%B6%E6%98%AF%E5%90%A6%E4%B8%80%E8%87%B4/ba-p/13550259" target="_blank">Using Custom Logic in SAP S/4HANA Cloud to check if the payment terms of pre made invoices are consistent with those in supplier master data | SAP Blogs</A>&nbsp;and <A href="https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-sap/%E5%9C%A8-sap-s-4hana-cloud-%E4%B8%AD%E9%80%9A%E8%BF%87%E8%87%AA%E5%AE%9A%E4%B9%89%E9%80%BB%E8%BE%91%E6%A3%80%E6%9F%A5%E9%A2%84%E5%88%B6%E5%8F%91%E7%A5%A8%E7%9A%84%E4%BB%98%E6%AC%BE%E6%9D%A1%E4%BB%B6%E4%B8%8E%E4%BE%9B%E5%BA%94%E5%95%86%E4%B8%BB%E6%95%B0%E6%8D%AE%E4%B8%AD%E7%9A%84%E4%BB%98%E6%AC%BE%E6%9D%A1%E4%BB%B6%E6%98%AF%E5%90%A6%E4%B8%80%E8%87%B4/ba-p/13550259" target="_self">Using Custom Logic in SAP S/4HANA Cloud to restrict invoicing of purchase orders with incomplete receipts | SAP Blogs</A>&nbsp;.</P><P>First, we need to add an enhancement implementation in the application - Custom Logic of SAP S/4HANA Cloud system. According to the business scenario, select the business context <STRONG>Procurement: Supplier Invoice</STRONG> and business add-in description <STRONG>Check Invoice Data</STRONG>, and fill in the implementation description and implementation identifier.</P><P>2. After adding the enhancement implementation in Custom Logic, we need to find the CDS Views that can provide the business requirement fields. After testing, for the same PO + ITEM + goods receipt, if it has already been posted, the same goods receipt document cannot be selected again for repeated parking. Therefore, the fields I use as validation conditions here are PO and ITEM numbers. At the same time, since we need to check whether this PO and ITEM have already been posted, we need to use <STRONG>SUPPLIERINVOICESTATUS = '5'</STRONG> in <STRONG>I_SupplierInvoiceAPI01</STRONG>. However, this CDS View does not have the PO and ITEM fields, so we need to use <STRONG>I_SuplrInvcItemPurOrdRefAPI01</STRONG>. In the sample code below, I used a custom CDS View. You can create a custom CDS View <STRONG>YY1_I_SUPPLIERINVOICEAPI01</STRONG> in your own system based on <STRONG>I_SupplierInvoiceAPI01</STRONG>, select the corresponding fields, and make adjustments.</P><P>At the same time, as I mentioned in my previous articles, in the sample code provided by the BAdI, we can find statements that can restrict the behavior that triggers the BAdI. According to our needs, we need to add the following statement to restrict the BAdI to only trigger during invoice parking, without affecting other processes:</P><P>Park: if_ex_mrm_check_invoice_cloud=&gt;c_Action_Park</P><P>3. Based on the above analysis, implement the BAdI. The specific code is as follows.</P><pre class="lia-code-sample language-abap"><code>loop at ITEMSWITHPOREFERENCE REFERENCE INTO DATA(Supinvoice_item). if action = if_ex_mrm_check_invoice_cloud=&gt;c_Action_Hold. select single from YY1_I_SUPPLIERINVOICEAPI01 with privileged access where PURCHASEORDER = @Supinvoice_item-&gt;PURCHASEORDER and PURCHASEORDERITEM = @Supinvoice_item-&gt;PURCHASEORDERITEM and SUPPLIERINVOICESTATUS = '5' into (Is_Supinvoice_status) . if Is_Supinvoice_status = abap_true. append value #( messagetype = 'E' messageid = 'MRM_BADI_CLOUD' messagenumber = '001' messagevariable1 = '暂存的发票有重复项目。' ) to messages. endif. endif. endloop.</code></pre><H2 id="toc-hId-1175999196">Conclusion:</H2><P>By reading this article and several previous blogs on similar scenarios, I hope you now understand how to use custom logic to apply certain restrictions when creating preliminary invoices for purchase orders.<BR />You can find more information about SAP S/4HANA Cloud procurement-related issues at the following link: <A href="https://community.sap.com/t5/c-khhcw49343/SAP+S%25252F4HANA+Cloud+Public+Edition+Sourcing+and+Procurement/pd-p/a906d110-8210-4641-9e54-4744b42f06d0" target="_self">SAP S/4HANA Cloud Public Edition Sourcing and Procurement - SAP Community</A></P><P>You can also read more blogs about SAP S/4HANA Cloud procurement at the following link: <A href="https://community.sap.com/t5/c-khhcw49343/SAP+S%25252F4HANA+Cloud+Public+Edition+Sourcing+and+Procurement/pd-p/a906d110-8210-4641-9e54-4744b42f06d0" target="_self">SAP S/4HANA Cloud Public Edition Sourcing and Procurement - SAP Community</A></P><P>If you have any suggestions or thoughts about this article, please feel free to share them in the comments section. I look forward to communicating with you. You are also welcome to follow my personal account, and I look forward to seeing you in the next blog post!</P> 2025-11-20T04:38:24.793000+01:00 https://community.sap.com/t5/abap-blog-posts/tracing-smart-forms-and-driver-programs-from-output-types-in-sap-debugging/ba-p/14242040 Tracing Smart Forms and Driver Programs from Output Types in SAP – Debugging Made Easy. 2025-11-20T06:40:31.588000+01:00 Bikash_R https://community.sap.com/t5/user/viewprofilepage/user-id/1527809 <P><FONT face="times new roman,times"><FONT color="#000080"><STRONG><FONT color="#000000">Introduction: --</FONT>&nbsp;</STRONG></FONT></FONT></P><P><FONT face="times new roman,times" color="#000000"><SPAN>Smart Forms are widely used in SAP to generate business outputs like Order Confirmations, Billing Documents, etc. However, identifying which Smart Form and driver program are linked to a particular output type, and how to debug them, is not always straightforward.<SPAN>&nbsp;</SPAN></SPAN></FONT></P><P><FONT face="times new roman,times" color="#000000"><STRONG>This blog provides a clear and separate step-by-step guide for: --</STRONG><EM><STRONG><SPAN>&nbsp;</SPAN></STRONG></EM></FONT></P><UL><LI><FONT face="times new roman,times" color="#000000"><FONT face="times new roman,times"><SPAN>Sales Orders (VA03) – Application V1<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>Billing Documents (VF03) – Application V3</SPAN></FONT></FONT><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN><SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></FONT></LI></UL><P><FONT face="times new roman,times" color="#000000"><STRONG>We'll cover how to: -</STRONG></FONT></P><UL><LI><FONT face="times new roman,times" color="#000000"><FONT face="times new roman,times"><SPAN>Identify the driver program and Smart Form<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT face="times new roman,times" color="#000000"><FONT face="times new roman,times"><SPAN>Trigger and debug the output<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT face="times new roman,times" color="#000000"><FONT face="times new roman,times"><SPAN>Trace the data flow using breakpoints</SPAN></FONT></FONT></LI></UL><P><FONT face="times new roman,times" color="#000000"><STRONG>Section 1: Sales Orders (VA03 – Application V1)&nbsp;</STRONG></FONT></P><P><FONT face="times new roman,times" color="#000000"><STRONG>Step 1: Identify Output Type Configuration&nbsp;</STRONG></FONT></P><UL><LI><FONT face="times new roman,times" color="#000000"><FONT face="times new roman,times"><SPAN>Go to <STRONG><SPAN>T-code NACE<SPAN>&nbsp;</SPAN></SPAN></STRONG></SPAN></FONT></FONT></LI></UL><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_0-1760340278376.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326485i3286B5A3059C8F08/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_0-1760340278376.png" alt="Bikash_11_0-1760340278376.png" /></span></FONT></P><UL><LI><FONT color="#000000"><SPAN class=""><SPAN class=""><FONT face="times new roman,times">Choose</FONT><SPAN class=""><FONT face="times new roman,times"> Application: </FONT><SPAN class=""><SPAN class=""><FONT face="times new roman,times">V1 (Sales)</FONT></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></LI></UL><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_1-1760340300691.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326486i8D7467EAB3E450C8/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_1-1760340300691.png" alt="Bikash_11_1-1760340300691.png" /></span></FONT></P><UL><LI><FONT face="times new roman,times" color="#000000"><SPAN class=""><SPAN class="">Click<SPAN class=""> on <SPAN class=""><SPAN class="">Output Types<SPAN class="">.<SPAN class="">&nbsp;</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></LI></UL><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_2-1760340322878.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326487i03F25168874FDA29/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_2-1760340322878.png" alt="Bikash_11_2-1760340322878.png" /></span></FONT></P><UL><LI><FONT color="#000000"><SPAN class=""><SPAN class=""><FONT face="times new roman,times">Select </FONT><SPAN class=""><FONT face="times new roman,times">output</FONT><SPAN class=""><FONT face="times new roman,times"> type and click </FONT><SPAN class=""><SPAN class=""><FONT face="times new roman,times">"Processing Routines"</FONT><SPAN class=""><FONT face="times new roman,times">.</FONT><SPAN class="">&nbsp;</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></LI></UL><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_4-1760340570956.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326490i259582C85975CD60/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_4-1760340570956.png" alt="Bikash_11_4-1760340570956.png" /></span></FONT></P><P><FONT color="#000000"><FONT face="times new roman,times"><STRONG>Here You’ll see: --</STRONG></FONT></FONT></P><UL><LI><FONT color="#000000"><FONT face="times new roman,times">Driver Program&nbsp;&nbsp;</FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times">Form Routine&nbsp;</FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times">Smart Form name</FONT></FONT></LI></UL><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_5-1760340602372.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326491iF7229ED42A4BD753/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_5-1760340602372.png" alt="Bikash_11_5-1760340602372.png" /></span></FONT></P><P><FONT face="times new roman,times" color="#000000">Then we will go to the driver program and put the debugger point.</FONT></P><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_6-1760340640922.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326492i29CA9BD6663B8099/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_6-1760340640922.png" alt="Bikash_11_6-1760340640922.png" /></span></FONT></P><P><FONT face="times new roman,times" color="#000000"><STRONG>Debug via VA03: -- </STRONG></FONT></P><UL><LI><FONT color="#000000"><FONT face="times new roman,times">Go to VA03, enter a valid sales order. </FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times">Navigate to Extras → Output → Header → Print Preview. </FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times">The system triggers the output program, and if you've placed breakpoints in the identified driver program, it enters debugging mode.</FONT></FONT></LI></UL><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_7-1760340769030.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326493i473B8675F57FEB78/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_7-1760340769030.png" alt="Bikash_11_7-1760340769030.png" /></span></FONT></P><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_8-1760340774360.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326494i411A853259D438C1/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_8-1760340774360.png" alt="Bikash_11_8-1760340774360.png" /></span></FONT></P><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_9-1760340780200.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326495i8E1FB4248C7C6DD6/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_9-1760340780200.png" alt="Bikash_11_9-1760340780200.png" /></span></FONT></P><P><FONT color="#000000"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_10-1760340785264.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326496i142AE56962D9C240/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_10-1760340785264.png" alt="Bikash_11_10-1760340785264.png" /></span></FONT><FONT color="#000000"><STRONG><FONT face="times new roman,times">Section 2: Billing Documents (VF03 – Application V3) </FONT></STRONG></FONT></P><P><FONT color="#000000"><STRONG><FONT face="times new roman,times">Step 1: Identify Output Type Configuration </FONT></STRONG></FONT></P><UL><LI><FONT color="#000000"><FONT face="times new roman,times">Go to T-code NACE.</FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times">Choose Application: V3 (Billing).</FONT></FONT></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_12-1760340990662.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326500iFD9E6EF9AF2146B4/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_12-1760340990662.png" alt="Bikash_11_12-1760340990662.png" /></span></P><UL><LI><FONT face="times new roman,times" color="#000000">Click on Output Types.</FONT></LI><LI><FONT face="times new roman,times" color="#000000">Select output type and click "Processing Routines".</FONT></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_13-1760341029656.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326501iE1C22E5C1EE8DCF0/image-size/medium?v=v2&amp;px=400" role="button" title="Bikash_11_13-1760341029656.png" alt="Bikash_11_13-1760341029656.png" /></span></P><P><FONT color="#000000"><STRONG><FONT face="times new roman,times">Here You’ll see: -- </FONT></STRONG></FONT></P><UL><LI><FONT color="#000000"><FONT face="times new roman,times">Driver Program </FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times">Form Routine </FONT></FONT></LI><LI><FONT color="#000000"><FONT face="times new roman,times">Smart Form information</FONT></FONT></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_14-1760341090799.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326503i02C31FE1BF2F20AD/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_14-1760341090799.png" alt="Bikash_11_14-1760341090799.png" /></span></P><P><FONT face="times new roman,times" color="#000000">Then we will go to the driver program and put the debugger point.</FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_15-1760341137995.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326504iEB1A31D5340FD361/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_15-1760341137995.png" alt="Bikash_11_15-1760341137995.png" /></span></P><P><FONT face="times new roman,times" color="#000000"><STRONG>Trigger and Debug Output from VF03: -- </STRONG></FONT></P><UL><LI><FONT face="times new roman,times">Access VF03, input the billing document. </FONT></LI><LI><FONT face="times new roman,times">Navigate to Goto → Header → Output, select the output type and choose Repeat Output. </FONT></LI><LI><FONT face="times new roman,times">Use the Further Data option to configure the output's request for reprocessing. </FONT></LI><LI><FONT face="times new roman,times">To manually trigger debugging: -</FONT><FONT face="times new roman,times">-</FONT></LI><LI><FONT face="times new roman,times">Use Program RSNAST00 </FONT></LI><LI><FONT face="times new roman,times">Provide relevant document and output type details </FONT></LI><LI><FONT face="times new roman,times">Execute to simulate output processing and hit breakpoints</FONT></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_16-1760341314956.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326523i1AD7C657A5F9D422/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_16-1760341314956.png" alt="Bikash_11_16-1760341314956.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_17-1760341320391.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326527iB26BCB283DEE4D07/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_17-1760341320391.png" alt="Bikash_11_17-1760341320391.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_18-1760341326001.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326532i502D0665C85591EC/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_18-1760341326001.png" alt="Bikash_11_18-1760341326001.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_19-1760341331108.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326537i601EFA8E65D2BE42/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_19-1760341331108.png" alt="Bikash_11_19-1760341331108.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_20-1760341336621.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326538i622FC7A54CA78F8E/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_20-1760341336621.png" alt="Bikash_11_20-1760341336621.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_21-1760341372138.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326540i5A238EA1267D9465/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_21-1760341372138.png" alt="Bikash_11_21-1760341372138.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_22-1760341378224.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326541iAA398DF2DC99F774/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_22-1760341378224.png" alt="Bikash_11_22-1760341378224.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_23-1760341400744.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326542i961D6E35845C8358/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_23-1760341400744.png" alt="Bikash_11_23-1760341400744.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_11_25-1760341414862.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/326545i19562E280C1F3FD6/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_11_25-1760341414862.png" alt="Bikash_11_25-1760341414862.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_0-1763120530904.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/340645i462F98EEB4906A1E/image-size/large/is-moderation-mode/true?v=v2&amp;px=999" role="button" title="Bikash_R_0-1763120530904.png" alt="Bikash_R_0-1763120530904.png" /></span></P><P><FONT color="#000000"><STRONG><FONT face="times new roman,times">Remember: -- </FONT></STRONG></FONT></P><P><FONT face="times new roman,times" color="#000000">Debugging Smart Forms is not just about fixing errors. it's about understanding the full flow from document to output and ensuring quality deliverables to your business users.</FONT></P><P><FONT size="5" color="#000000"><STRONG><FONT face="times new roman,times">Conclusion: --</FONT></STRONG></FONT></P><P><FONT face="times new roman,times" color="#000000">Understanding how to trace and debug Smart Forms and their associated driver programs is essential for any SAP ABAP developer or functional consultant involved in output management.</FONT></P><P><FONT face="times new roman,times" color="#000000">By following the structured steps for Sales (VA03 - V1) and Billing (VF03 - V3) provided in this blog, you can:</FONT></P><UL><LI><FONT face="times new roman,times" color="#000000">Quickly locate the output type configuration using NACE.</FONT></LI><LI><FONT face="times new roman,times" color="#000000">Identify the correct driver program and Smart Form.</FONT></LI><LI><FONT face="times new roman,times" color="#000000">Set effective breakpoints and debug output logic.</FONT></LI><LI><FONT face="times new roman,times" color="#000000">Use tools like RSNAST00, and SOST for monitoring and troubleshooting.</FONT></LI><LI><FONT face="times new roman,times" color="#000000">Ensure correct data is passed from application documents to the Smart Form output</FONT></LI></UL><P><FONT color="#000000"><STRONG><FONT face="times new roman,times">Thank You__</FONT></STRONG></FONT></P> 2025-11-20T06:40:31.588000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/simple-understanding-of-hierarchies-in-sap-s-4hana-embedded-analytics-part/ba-p/14274085 Simple understanding of Hierarchies in SAP S/4HANA Embedded Analytics– Part 1 (Basics) 2025-11-21T12:47:55.322000+01:00 PriyRatanShukla https://community.sap.com/t5/user/viewprofilepage/user-id/1864914 <H3 id="ember53" id="toc-hId-1894651232">Accurate CDS hierarchy modeling and understanding is critical for financial reporting and operational analytics. Without well-defined hierarchies, drill-down analysis and aggregated insights become challenging. This blog demystifies hierarchy concepts in SAP S/4HANA Embedded Analytics and shows how they power SAC,Multidimensiona Reports , AFO and Datasphere scenarios.This blog will give you the basic understanding of Hierarchies in CDS Views (S4 Hana)</H3><H3 id="ember55" id="toc-hId-1698137727">What This Blog Covers</H3><UL><LI>Common hierarchy terminologies</LI><LI>Types of hierarchies in CDS Views</LI><LI>Standard hierarchies in S/4HANA</LI><LI>Why custom hierarchies matter</LI></UL><H3 id="ember57" id="toc-hId-1501624222"><BR />1. Key Terminologies-</H3><P class="">Before diving into implementation, let’s clarify the basics:</P><UL><LI><STRONG>Root Node </STRONG>: Top-most node in the hierarchy. Has <STRONG>No parent</STRONG>. Signifies the Hierarchy Structure and contains the Hierarchy metadata. A hierarchy can have several root nodes.</LI><LI><STRONG>Hierarchy Node </STRONG>: Represents a group or element in the hierarchy.</LI><LI><STRONG>Parent Node </STRONG>: A node that has child nodes beneath it.</LI><LI><STRONG>Child Node </STRONG>: Belongs to a parent node.</LI><LI><STRONG>Leaf Node </STRONG>: Lowest node in the hierarchy (end point).</LI><LI><STRONG>Hierarchy Directory </STRONG>: Stores hierarchy definitions.</LI><LI><STRONG>Siblings </STRONG>: Nodes sharing the same parent.</LI><LI><STRONG>Hierarchy Level </STRONG>: Indicates depth of a node in the hierarchy. Levels can be defined as 0,1,2,3 . In S/4 EA change level based hierarchies to Parent child hierarchies .</LI><LI><STRONG>Recursive Hierarchy</STRONG>: Nodes can reference themselves (e.g., Org Structure). Implemented using <STRONG>self-association</STRONG> in CDS.</LI><LI><STRONG>Hierarchy Node Texts</STRONG>: These contain the descriptive names or labels associated with the hierarchy nodes, typically derived from the related master data (for example, the name or description of a General Ledger account or Product Hierarchy Description).</LI><LI><STRONG>Orphan nodes</STRONG>, These are the nodes missing a link to a root. You can choose to ignore them, raise an error, or promote them as alternative roots using annotations like ORPHANS = ROOT</LI></UL><HR /><H3 id="ember60" id="toc-hId-1305110717">2. Example of a Hierarchy-</H3><PRE><CODE>Company → Product Category → Product → Variant Shoe Model 1 </CODE></PRE><P class="">Example:</P><UL><LI><STRONG>Company (ABC Corp)</STRONG>&nbsp; → Root Node -&gt; The top most node in hierarchy (Defined via Hierarchy Directory and <EM>Root node has no parent defined</EM>)---- To be discussed in details in another Part 2.</LI><LI><STRONG>Product Category (Footwear)</STRONG>&nbsp; → Child of Company-&gt;A Parent Node for Product but this is not the Root node(Since it has Company as a Parent Node).</LI><LI><STRONG>Product (Shoes)</STRONG>&nbsp; → Child of Product Category-&gt;Parent Node for Variant</LI><LI><STRONG>Variant (Shoe Model 1)</STRONG>&nbsp; → Leaf Node-&gt;Lowest Node in the hierarchy</LI></UL><P class="">&nbsp;In SAP: For <STRONG>Cost Center</STRONG> or <STRONG>Profit Center</STRONG> hierarchy, <STRONG>Controlling Area</STRONG> could be the root node.</P><HR /><H3 id="ember65" id="toc-hId-1108597212">3. Types of Hierarchies in CDS Views-</H3><P class="">In <STRONG>S/4HANA Embedded Analytics</STRONG>, hierarchies are modeled using CDS annotations. Most common type:</P><UL><LI><STRONG>Parent-Child Hierarchy <span class="lia-unicode-emoji" title=":link:">🔗</span></STRONG> Always recursive. Each node references its parent, forming a tree structure. Example: Cost Center hierarchy where each cost center belongs to a higher-level.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="hier2.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/343306i9EBAFBA9803859A0/image-size/large?v=v2&amp;px=999" role="button" title="hier2.png" alt="hier2.png" /></span>&nbsp;</P><UL><LI><STRONG>Level-Based Hierarchy</STRONG> <STRONG><span class="lia-unicode-emoji" title=":link:">🔗</span></STRONG>Not supported in S4 Hana Embedded analytics as Analytical engine supports only Parent Child Hierarchy for drill downs and aggregations.</LI></UL><P class=""><STRONG>CDS Annotation Example</STRONG>:</P><PRE><CODE>@Hierarchy.parentChild: { recurse:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; parent: 'ParentNode',&nbsp;&nbsp; child:&nbsp; 'HierarchyNode'&nbsp;&nbsp; }, siblingsOrder:&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; by: 'SequenceNumber',&nbsp;&nbsp;&nbsp; direction: 'ASC'&nbsp;&nbsp; }, directory:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '_Hierarchy' }</CODE></PRE><HR /><H3 id="ember71" id="toc-hId-912083707">4. Standard Hierarchies in S/4HANA-</H3><P class="">SAP delivers several predefined hierarchies:</P><UL><LI>Cost Center Hierarchy – For controlling and cost reporting</LI><LI>Profit Center Hierarchy – For profitability analysis</LI><LI>GL Account Hierarchy – For financial statements</LI><LI>Product Hierarchy – For material classification</LI><LI>EHS Location Hierarchies – For Environment, Health &amp; Safety compliance</LI></UL><HR /><H3 id="ember74" id="toc-hId-715570202">5. Custom Hierarchies-</H3><P class="">Business requirements often demand custom hierarchies:</P><UL><LI>Example: A sales region hierarchy combining geography and product lines.</LI><LI>Implemented using CDS Views by developing a relation between Dimension Views and Hierarchy View.</LI></UL><HR /><H3 id="ember77" id="toc-hId-519056697">6. Why Hierarchies Matter?</H3><UL><LI>Enable <STRONG>drill-down reporting</STRONG> in SAC or Fiori Multidimensional Reports/AFO.</LI><LI>Support <STRONG>aggregations at multiple levels</STRONG></LI><LI>Provide <STRONG>flexibility for planning and analytics</STRONG></LI></UL><HR /><H3 id="ember79" id="toc-hId-322543192">7. Technical Details: Where Hierarchies Are Stored-</H3><UL><LI><STRONG>HRRP_NODE_N Table</STRONG>: Stores <STRONG>Parent Node info</STRONG>, hierarchy node level details, and relationships between nodes(Example where GL Account/Profit Center/Cost Center Hierarchy details are stored).</LI><LI><STRONG>HRRP_DIR_N Table</STRONG>: Stores <STRONG>Hierarchy Directory info</STRONG> (name, version, metadata).</LI></UL><P class=""><span class="lia-unicode-emoji" title=":backhand_index_pointing_right:">👉</span>When you activate or create a hierarchy (standard or custom), these tables are updated.</P><UL><LI><STRONG>HRRP_NODE_N</STRONG> = Node-level details (Parent-Child relationships)</LI><LI><STRONG>HRRP_DIR_N</STRONG> = Directory-level details (Hierarchy header info)</LI></UL><H3 id="ember83" id="toc-hId-126029687">8. Hierarchy Components &amp; Annotations-</H3><UL><LI>A well-defined hierarchy in CDS has multiple views:</LI></UL><P class=""><STRONG>Source(Master Data) View</STRONG>: Provides key fields and relationships (Eg GL Account/Cost Center/Product related details).<BR /><STRONG>Hierarchy View</STRONG>: Contains the relationships and parent–child links. Eg - Hierarchy(Child) Node, Parent Node, Node levels etc.<BR /><STRONG>Directory View</STRONG>: Provides metadata about hierarchy variants -- Optional.<BR /><STRONG>Text Views</STRONG> for labeling nodes and directory entries . Eg: GL account and it's text/ Cost center and it's text etc.</P><P class="">Proper annotations (@Hierarchy.parentChild, @ObjectModel.dataCategory: #HIERARCHY) control recursion, sibling order, orphan handling, and directory association</P><P class=""><STRONG><EM>Notes</EM></STRONG><STRONG>:</STRONG></P><UL><LI><STRONG>Parent–Child Hierarchy: </STRONG>Supported in CDS for analytics; recursive structure.</LI><LI><STRONG>Level-Based Hierarchy: </STRONG>Not supported in CDS for analytical consumption (only parent–child works for drill-down).</LI><LI>Orphan nodes = Nodes without a parent.</LI><LI><EM>A Parent Node can have multiple Hierarchy Nodes/Child nodes but a hierarchy node cannot have multiple parents</EM></LI><LI>A node can appear under different parents <STRONG>in different hierarchy versions</STRONG>, not in the same hierarchy( It usually refers to <STRONG>alternate hierarchy versions or variants</STRONG>, not simultaneous parents in the same hierarchy. For example:</LI></UL><P class=""><STRONG>Hierarchy Variant/Version 1</STRONG>: Region → Country → City</P><P class=""><STRONG>Hierarchy Variant/Version 2</STRONG>: Sales Channel → Country → City.This is managed via <STRONG>Hierarchy Directory</STRONG>.</P><UL><LI>A CDS hierarchy cannot serve as the underlying source for building another CDS hierarchy.</LI></UL><HR /><H3 id="ember95" id="toc-hId--145715187">Next Article (Part 2)</H3><UL><LI>How to <STRONG>activate Standard hierarchies and develop Custom Hierarchies in CDS Views</STRONG> (S4 Hana EA).</LI><LI>How to <STRONG>consume hierarchies in SAC</STRONG></LI></UL> 2025-11-21T12:47:55.322000+01:00 https://community.sap.com/t5/technology-blog-posts-by-sap/an-end-to-end-hands-on-tutorial-for-clean-core-rap-development/ba-p/14276157 An End-to-End Hands-On Tutorial for Clean Core RAP Development 2025-11-28T12:18:20.855000+01:00 iulia2 https://community.sap.com/t5/user/viewprofilepage/user-id/1721086 <H1 id="toc-hId-1636546246">Introduction</H1><P>In this workshop, we will build a simple <STRONG>Item business object</STRONG> using the ABAP RESTful Application Programming Model (RAP) on an SAP BTP trial system.</P><P>RAP is SAP’s <STRONG>strategic programming model</STRONG> for developing cloud-ready, Fiori-enabled business applications in ABAP. It provides a <STRONG>clean, end-to-end programming model</STRONG> where you can define business objects, behaviors, services, and UI-ready projections in a structured way.</P><P>In this blog, we will:</P><UL><LI><P>Create a <STRONG>database table</STRONG> for items.</P></LI><LI><P>Define <STRONG>CDS root and projection views</STRONG>.</P></LI><LI><P>Implement <STRONG>behavior definitions</STRONG> with CRUD, and enhance it with actions, validations and determinations.</P></LI><LI><P>Expose the business object as an <STRONG>OData service</STRONG>.</P></LI><LI><P>Preview it in <STRONG>Fiori</STRONG>.</P></LI><LI><P>Model relationships using associations and compositions between entities.</P></LI><LI><P>Implement value helps to improve user input and Fiori UX.</P></LI></UL><P>By the end, you will understand how RAP objects are structured, connected, and how Clean Core principles are applied in a real example.</P><H2 id="toc-hId-1569115460"><STRONG>Why RAP?</STRONG></H2><UL><LI><P><STRONG>Cloud-ready:</STRONG> SAP’s standard for S/4HANA cloud extensions and custom apps.</P></LI><LI><P><STRONG>Clean Core compliant:</STRONG> No modifications to standard objects; all extensibility is via APIs.</P></LI><LI><P><STRONG>End-to-end model:</STRONG> Business logic, UI, draft handling, and authorizations all in one place.</P></LI><LI><P><STRONG>Consistency:</STRONG> Automatic CRUD, locking, and draft handling.</P></LI><LI><P><STRONG>Fiori-ready:</STRONG> Generates OData services consumable by Fiori Elements.</P></LI><LI><P><STRONG>Productivity:</STRONG> Faster development than classical ABAP or BOPF.</P></LI></UL><H1 id="toc-hId-1243519236">Environment Setup</H1><P>For this demo, we use <STRONG>ABAP Development Tools (ADT) in Eclipse</STRONG> connected to an <STRONG>ABAP on Cloud project</STRONG> on an SAP BTP trial system. This setup gives us access to all RAP development tools and lets us preview Fiori apps directly from Eclipse.</P><P>If you’re setting this up for the first time, SAP provides a step-by-step tutorial to i<SPAN>nstall </SPAN>Eclipse IDE, a<SPAN>dd the </SPAN>ABAP Development Tools (ADT) plugin and c<SPAN>onnect to your SAP system.&nbsp;<A title="Download the Eclipse IDE and add the ABAP Development Tools (ADT) Plugin | SAP Tutorials" href="https://developers.sap.com/tutorials/abap-install-adt..html" target="_blank" rel="noopener noreferrer">Download the Eclipse IDE and add the ABAP Development Tools (ADT) Plugin | SAP Tutorials</A>&nbsp;<BR /></SPAN></P><H2 id="toc-hId-1176088450">Useful ADT Shortcuts</H2><P>Here are some useful ADT keyboard shortcuts for the ABAP development in Eclipse.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="shortcuts.png" style="width: 665px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344461iC0BAD5F430FFCA6D/image-size/large?v=v2&amp;px=999" role="button" title="shortcuts.png" alt="shortcuts.png" /></span></P><P><STRONG>Info</STRONG><SPAN>: You can display the full list of available shortcuts in the</SPAN><SPAN>&nbsp;</SPAN><STRONG>Show Key Assit</STRONG><SPAN>&nbsp;</SPAN><SPAN>in ADT by pressing</SPAN><SPAN>&nbsp;</SPAN><STRONG>Ctrl+Shift+L</STRONG><SPAN>.</SPAN></P><H1 id="toc-hId-850492226">&nbsp;</H1><H1 id="toc-hId-653978721">Part 1: Simple BO</H1><H2 id="toc-hId-586547935">Step 1: Create a Package</H2><P>Before creating RAP objects, we need a <STRONG>package</STRONG> to organize them. Packages are like folders in Eclipse—they help manage all the development objects together.</P><P>1. In Eclipse, right-click your <STRONG>ABAP on Cloud project</STRONG> → <STRONG>New</STRONG> → <STRONG>ABAP Package</STRONG>.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="1.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344473iDBF146E378CCC4E9/image-size/medium?v=v2&amp;px=400" role="button" title="1.png" alt="1.png" /></span></P><P>2.&nbsp;Enter package details</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="2.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344475iB215BAC9F968C11A/image-size/medium?v=v2&amp;px=400" role="button" title="2.png" alt="2.png" /></span></STRONG></P><P><STRONG>&nbsp;</STRONG></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><STRONG>Why this matters:</STRONG></P><UL><LI><P>All RAP objects (tables, CDS views, behavior definitions, service definitions) should be in the same package.</P></LI><LI><P>It ensures <STRONG>clean core compliance</STRONG>, meaning your custom objects don’t modify standard SAP objects directly.</P></LI></UL><P>&nbsp;</P><H2 id="toc-hId-390034430">Step 2: Create Database Table</H2><P>The database table is the foundation of your RAP business object. For this example, we’ll create a table called ZITEM02 for our Item BO.&nbsp;</P><P>1. Right-click your package → <STRONG>New</STRONG> → <STRONG>Other Repository Object&nbsp;→</STRONG>&nbsp;search for <STRONG>"Database Table".</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="3.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344477iEA014D963338068F/image-size/medium?v=v2&amp;px=400" role="button" title="3.png" alt="3.png" /></span><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="4.png" style="width: 356px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344479i4DADF5F9D023EA19/image-dimensions/356x301?v=v2" width="356" height="301" role="button" title="4.png" alt="4.png" /></span></P><P>2. Add the fields and mark <FONT face="courier new,courier">item_id&nbsp;</FONT>as the <STRONG>primary key</STRONG>.</P><pre class="lia-code-sample language-abap"><code>@EndUserText.label : 'Item Table' @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE @AbapCatalog.tableCategory : #TRANSPARENT @AbapCatalog.deliveryClass : #A @AbapCatalog.dataMaintenance : #RESTRICTED define table zitem_02 { key client : abap.clnt not null; key item_id : sysuuid_x16 not null; name : abap.char(50) not null; description : abap.char(100); price : abap.dec(10,2); status_code : abap.char(5) not null; local_created_by : abp_creation_user; local_created_at : abp_creation_tstmpl; local_last_changed_by : abp_locinst_lastchange_user; local_last_changed_at : abp_locinst_lastchange_tstmpl; last_changed_at : abp_lastchange_tstmpl; }</code></pre><P>3. Activate the table.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="5.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344481i41330E6D10684F13/image-size/large?v=v2&amp;px=999" role="button" title="5.png" alt="5.png" /></span></P><P>The table <FONT face="courier new,courier">ZITEM_02&nbsp;</FONT>serves as the <STRONG>persistent layer</STRONG> for your RAP business object. All data is stored here.&nbsp;</P><P>&nbsp;</P><P><STRONG>Administrative Fields:</STRONG></P><P><FONT face="courier new,courier">local_created_by</FONT>/ <FONT face="courier new,courier">local_created_at</FONT> → track <STRONG>who created</STRONG> the record and <STRONG>when</STRONG>.</P><P><FONT face="courier new,courier">local_last_changed_by</FONT> / <FONT face="courier new,courier">local_last_changed_at&nbsp;</FONT>→ track <STRONG>local changes</STRONG> before activation (important for draft-enabled objects).</P><P><FONT face="courier new,courier">last_changed_at</FONT> → tracks the <STRONG>last committed change</STRONG>; used as the <STRONG>ETag</STRONG> for locking and consistency.</P><P><STRONG>Why Admin Fields Matter:</STRONG></P><P>RAP automatically uses them for <STRONG>draft management, locking, and optimistic concurrency control</STRONG>. Even if your app is simple, including them makes your BO <STRONG>ready for enhancements</STRONG> such as validations, actions, and side effects.</P><H1 id="toc-hId-64438206">&nbsp;</H1><H2 id="toc-hId--2992580">Step 3: Create CDS&nbsp;</H2><H3 id="toc-hId--145654735">1. Root View&nbsp;</H3><P>The root view sits on top of the database table and defines the <STRONG>entity structure</STRONG> for your business object. It is the source for the <STRONG>behavior definition</STRONG>.</P><P>1.&nbsp;Right-click the database table → <STRONG>New Data Definition</STRONG>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="6.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344483i505710536A39533D/image-size/large?v=v2&amp;px=999" role="button" title="6.png" alt="6.png" /></span></P><P>2. Select the <STRONG>Root View Entity</STRONG> template.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="7.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344484i3E216219E29E360D/image-size/medium?v=v2&amp;px=400" role="button" title="7.png" alt="7.png" /></span></P><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Root View Entity for Item' @Metadata.allowExtensions: true define root view entity ZR_ITEM_02 as select from zitem_02 { key item_id as ItemId, name as Name, description as Description, price as Price, status_code as StatusCode, local_created_by as LocalCreatedBy, local_created_at as LocalCreatedAt, local_last_changed_by as LocalLastChangedBy, local_last_changed_at as LocalLastChangedAt, last_changed_at as LastChangedAt }</code></pre><P>Table = raw persistence.</P><P>Root view = <STRONG>business-level representation</STRONG>, enriched with semantics, annotations, and ready for behavior logic.</P><P>The root view defines the <STRONG>primary key</STRONG>&nbsp;<FONT face="courier new,courier">item_id</FONT>&nbsp;to match the table.</P><H3 id="toc-hId--342168240">2. Projection View</H3><P>The projection view is built on top of the root view and serves as the entry point for service exposure. Here, we select which fields are exposed in the transactional OData service. We can also include UI annotations to guide Fiori Elements in rendering the app automatically.</P><P>1.&nbsp;Right-click the Root View CDS → <STRONG>New Data Definition</STRONG>&nbsp;</P><P>2. Select the <STRONG>Projection View</STRONG> template.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="8.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344487i2026ED2C88E5F7EA/image-size/medium?v=v2&amp;px=400" role="button" title="8.png" alt="8.png" /></span></P><P>The root view contains the core business data and logic, while the projection only exposes what the frontend needs. This way, we don’t modify or clutter the core data model with UI-specific details, keeping the core stable and extensible.</P><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Projection View for Item' @Metadata.allowExtensions: true define root view entity ZC_ITEM_02 provider contract transactional_query as projection on ZR_ITEM_02 { key ItemId, Name, Description, Price, StatusCode }</code></pre><P>For today, I’ll keep the UI annotations minimal here and show how to add them cleanly in a <STRONG>metadata extension</STRONG> later, which keeps our projection view tidy and focused on data exposure.</P><H1 id="toc-hId-48124269">&nbsp;</H1><H2 id="toc-hId--441792243">Step 4: Create Behavior Definition</H2><P>The behavior definition specifies how this entity behaves at runtime: which operations are allowed, It maps fields from the root view to the database table, and how draft actions are handled.</P><P>1.&nbsp;Right-click the Root View CDS → <STRONG>New Behavior Definition</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344493i20C5AB9D6E1378DC/image-size/large?v=v2&amp;px=999" role="button" title="9.png" alt="9.png" /></span></STRONG></P><P>Since the purpose of this first example is to display the list report, we only need to map fields from the root view to the database table.&nbsp;</P><pre class="lia-code-sample language-abap"><code>managed implementation in class zbp_r_item_02 unique; strict ( 2 ); define behavior for ZR_ITEM_02 alias Item persistent table zitem_02 lock master authorization master ( instance ) etag master LastChangedAt { create ( authorization : global ); update; delete; field ( readonly, numbering : managed ) ItemId; mapping for zitem_02 { ItemId = item_id; Name = name; Description = description; Price = price; StatusCode = status_code; LastChangedAt = last_changed_at; LocalCreatedAt = local_created_at; LocalCreatedBy = local_created_by; LocalLastChangedAt = local_last_changed_at; LocalLastChangedBy = local_last_changed_by; } }</code></pre><P>&nbsp;</P><UL><LI><P><STRONG>readonly</STRONG> → The field cannot be changed by the user. RAP ensures it is protected in the frontend and backend.</P></LI><LI><P><STRONG>numbering : managed</STRONG> → RAP automatically generates unique values for this field when a new entity is created. You don’t need to write your own logic for primary keys like UUIDs or sequences.</P><P>&nbsp;</P></LI></UL><P>The <STRONG>behavior projection</STRONG> allows us to expose only a subset of behavior from the main entity for a specific service. This is useful if we want different services to expose different parts of the behavior without modifying the core behavior definition.</P><pre class="lia-code-sample language-abap"><code>projection; strict ( 2 ); define behavior for ZC_ITEM_02 alias Item { use create; use update; use delete; }</code></pre><P>&nbsp;</P><H2 id="toc-hId--638305748">Step 5: Create Service Definition</H2><P>The service definition declares which projection views are exposed as OData services. Here, we expose our projection view, making our User BO available for Fiori or API consumption. Service definitions are protocol-agnostic and can later be consumed via different bindings.</P><pre class="lia-code-sample language-abap"><code>@EndUserText.label: 'Service Definition for Item' define service ZSD_ITEM { expose ZC_ITEM_02 as Item; }</code></pre><P>&nbsp;</P><H2 id="toc-hId--834819253">Step 6: Create Service Binding</H2><P>Right-click the Service Definition → <STRONG>New Service Binding</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="10.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344503i7EDC6EFEE17AD2C4/image-size/medium?v=v2&amp;px=400" role="button" title="10.png" alt="10.png" /></span></STRONG></P><P>Finally, the service binding connects the service definition to a specific protocol, such as OData V2 or V4. After activation, Publish the service and it can be accessed directly from Fiori elements or any OData client.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="11.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344507iF5E66C18ED2814DE/image-size/large?v=v2&amp;px=999" role="button" title="11.png" alt="11.png" /></span></P><P>&nbsp;</P><P>At this stage, our Business Object is not draft-enabled and does not support create/update/delete yet.<BR />This means the Fiori Elements application shows a <STRONG>read-only list report</STRONG>, and because the table is empty, the preview will be blank.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="12.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344541i8965C571AC46A4D0/image-size/large?v=v2&amp;px=999" role="button" title="12.png" alt="12.png" /></span></P><P>This step is intentional — it confirms that:</P><UL><LI><P>the CDS views are correct</P></LI><LI><P>the projection is exposed</P></LI><LI><P>the service binding is active</P></LI><LI><P>the app renders successfully with no errors</P></LI></UL><P>Even with no data, seeing the list report appear is an important milestone. In the next sections, we will add draft support and enable full CRUD operations.</P><H1 id="toc-hId--737929751">&nbsp;</H1><H1 id="toc-hId--934443256">Part 2: Enabling Draft, CRUD Operations, and Transactional Behavior in the RAP Business Object</H1><P>In<STRONG> Part 1</STRONG> of this series, we created the foundation of our RAP application:</P><UL><LI><P>A clean core–compliant database table</P></LI><LI><P>The CDS root view entity</P></LI><LI><P>The projection view</P></LI><LI><P>A minimal behavior definition</P></LI><LI><P>A service binding that exposes our object to Fiori</P></LI></UL><P>At that stage, the generated application was intentionally <STRONG>read-only</STRONG>, serving as a good starting point to verify that the service and CDS structure work correctly.</P><P>Now, in <STRONG>Part 2</STRONG>, we take the next major step: turning our read-only object into a <STRONG>full transactional Business Object</STRONG> using the managed RAP BO approach. This includes:</P><UL><LI><P>Activating <STRONG>Create</STRONG>, <STRONG>Update</STRONG>, and <STRONG>Delete</STRONG> support</P></LI><LI><P>Enabling <STRONG>Draft handling</STRONG> for safe data entry</P></LI><LI><P>Allowing the Fiori Elements app to automatically render UI flows such as Edit, Save, Delete, and Discard Draft</P></LI><LI><P>Preparing the BO for further business logic enhancements (which we will add in Part 3)</P></LI></UL><H2 id="toc-hId--1424359768"><STRONG>Why We Enable Draft in RAP?</STRONG></H2><P>Draft is one of the key features of Fiori Elements applications.</P><P>Before enabling it, it’s important to explain <EM>why</EM> draft is needed.</P><H3 id="toc-hId--1914276280"><STRONG>Users expect modern UI behavior</STRONG></H3><P>In modern SAP Fiori apps, users do not commit their changes immediately. Instead:</P><UL><LI><P>They can start editing an object.</P></LI><LI><P>Leave the page.</P></LI><LI><P>Navigate back later.</P></LI><LI><P>Recover their unsaved changes.</P></LI></UL><P>This improves the UX significantly and eliminates accidental data loss.</P><H3 id="toc-hId--1942606094"><STRONG>Draft prevents incomplete database commits</STRONG></H3><P>Draft ensures that:</P><UL><LI><P>Partial or inconsistent data is never saved.</P></LI><LI><P>Users can enter complex data in multiple steps.</P></LI><LI><P>Locks on active instances are minimized.</P></LI></UL><P>This is especially important in enterprise systems with many concurrent users.</P><H3 id="toc-hId--2139119599"><STRONG>RAP provides draft automatically</STRONG></H3><P>Thanks to RAP’s managed BO runtime, draft functionality requires <STRONG>no custom code</STRONG> — only a few declarations in the behavior definition.</P><P>&nbsp;</P><H2 id="toc-hId--2042230097">Step 1: Updating the Behavior Definition of the Root Entity</H2><P><STRONG>1. Add&nbsp;<FONT face="courier new,courier"><SPAN>with</SPAN> <SPAN>draft;</SPAN></FONT></STRONG></P><P><STRONG><SPAN>2. Add <FONT face="courier new,courier">draft table zitem_02_d;</FONT> </SPAN></STRONG></P><P>This associates the BO with a draft table.</P><P>If the draft table does not exist yet, ADT will offer to create it automatically.</P><P><SPAN><STRONG>3. Click on "Quick assist" ( CTRL + 1 )</STRONG> </SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="13.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344561i81FF83A799464957/image-size/large?v=v2&amp;px=999" role="button" title="13.png" alt="13.png" /></span></SPAN></P><DIV><DIV><P>&nbsp;</P></DIV></DIV><pre class="lia-code-sample language-abap"><code>@EndUserText.label : 'Draft table for entity ZR_ITEM_02' @AbapCatalog.enhancement.category : #EXTENSIBLE_ANY @AbapCatalog.tableCategory : #TRANSPARENT @AbapCatalog.deliveryClass : #A @AbapCatalog.dataMaintenance : #RESTRICTED define table zitem_02_d { key mandt : mandt not null; key itemid : sysuuid_x16 not null; name : abap.char(50); description : abap.char(100); price : abap.dec(10,2); statuscode : abap.char(5); localcreatedby : abp_creation_user; localcreatedat : abp_creation_tstmpl; locallastchangedby : abp_locinst_lastchange_user; locallastchangedat : abp_locinst_lastchange_tstmpl; lastchangedat : abp_lastchange_tstmpl; "%admin" : include sych_bdl_draft_admin_inc; }</code></pre><P>Draft tables contain:</P><UL><LI><P>Table fields</P></LI><LI><P>Administrator fields</P></LI><LI><P>Temporary user changes</P></LI></UL><P>This table supports parallel editing and safe drafts.</P><P><STRONG>4. Additional Draft Actions and What They Do</STRONG></P><P>In RAP, the draft handling pattern can be extended beyond the basic actions .<BR />For more advanced scenarios — especially when working with optimized draft flows, background checks, or multi-step editing — we can include the following actions:</P><pre class="lia-code-sample language-abap"><code> draft action Activate optimized; draft action Edit; draft action Discard; draft action Resume; draft determine action Prepare { }</code></pre><P>Beyond the basic Edit / Activate / Discard pattern, RAP provides additional draft actions to improve performance and user experience.</P><UL><LI><P><STRONG>Resume</STRONG> – restores an existing draft so users can continue where they left off.</P></LI><LI><P><STRONG>Prepare</STRONG> – pre-fills data before the user sees the draft instance.</P></LI></UL><P>These actions require no manual coding unless you want to enhance them, and together they deliver a modern, safe, Fiori-compliant editing workflow.</P><P><STRONG>5. Add&nbsp;<FONT face="courier new,courier"><SPAN>total</SPAN> <SPAN>etag</SPAN> <SPAN>LastChangedAt;</SPAN></FONT></STRONG></P><P>This ETag is used by RAP to guarantee concurrency and data consistency.<BR />It prevents situations where one user accidentally overwrites changes made by another user.<BR />It is also required for draft handling and for the Fiori Elements UI, which relies on this timestamp to detect outdated edits.<BR />RAP automatically manages this field, updating it whenever the record is changed.</P><P><STRONG>6. Update the Behavior Projection</STRONG></P><P>The projection behavior definition exposes the business behavior to the Fiori UI and the OData service. Even if the root BO supports create, update, delete, and draft actions, they must be explicitly enabled in the behavior projection. Without this step, Fiori Elements will not show the Create/Edit/Delete or draft buttons. The projection layer ensures clean core separation by keeping internal logic in the root BO while exposing only the required operations to the UI.</P><pre class="lia-code-sample language-abap"><code>projection; strict ( 2 ); use draft; define behavior for ZC_ITEM_02 alias Item { use create; use update; use delete; use action Activate; use action Edit; use action Discard; use action Resume; use action Prepare; }</code></pre><P><STRONG>7. Create Behavior Implementation Class&nbsp;</STRONG></P><P>Eclipse generates a global ABAP class with the naming convention.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="14.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344563i0F61B1FF8B9FE73D/image-size/large?v=v2&amp;px=999" role="button" title="14.png" alt="14.png" /></span></P><P>&nbsp;</P><P><STRONG>Understanding What “Managed Implementation” Means</STRONG></P><P><STRONG>Standard CRUD is generated automatically</STRONG></P><P>You <STRONG>do not</STRONG> need to write: create/ update/ delete logic, draft save/ load logic, locking logic, ETag management</P><P>RAP provides all of this out of the box.</P><P><STRONG>The class is only for custom behavior</STRONG></P><P>This is where we will later implement <STRONG>v</STRONG><STRONG>alidations</STRONG> (check input before save), <STRONG>d</STRONG><STRONG>eterminations</STRONG> (auto-fill fields),&nbsp;<STRONG>a</STRONG><STRONG>ctions</STRONG> (mark item as completed), <STRONG>u</STRONG><STRONG>nmanaged logic,</STRONG>&nbsp;<STRONG>feature control, a</STRONG><STRONG>uthorization checks</STRONG><SPAN>, if needed.</SPAN></P><P>But for Part 2 (Draft + CRUD), the class stays empty.</P><P><STRONG>8.&nbsp;Creating the Metadata Extension (UI Annotations)</STRONG></P><P>After creating the <STRONG>projection view</STRONG> and exposing the BO behavior, we need to define how this data should be displayed in Fiori Elements apps.</P><P>This is where <STRONG>metadata extensions</STRONG> come into play. They allow you to add UI annotations <STRONG>without touching the core CDS view</STRONG>, keeping your implementation clean and following <STRONG>Clean Core principles</STRONG>.</P><P>Right-click on the Consumption View → <STRONG>New</STRONG> → <STRONG>Metadata Extension</STRONG></P><pre class="lia-code-sample language-abap"><code>@Metadata.layer: #CORE annotate entity ZC_ITEM_02 with { @UI.facet: [ { purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'Items', position: 10 } ] ItemId; @UI.lineItem: [{ position: 10, label: 'Name' }] @UI.identification: [{ position: 10, label: 'Name' }] Name; @UI.lineItem: [{ position: 20, label: 'Description' }] @UI.identification: [{ position: 20, label: 'Description' }] Description; @UI.lineItem: [{ position: 30, label: 'Price' }] @UI.identification: [{ position: 30, label: 'Price' }] Price; @UI.lineItem: [{ position: 40, label: 'Status Code' }] @UI.identification: [{ position: 40, label: 'Status Code' }] StatusCode; }</code></pre><P>The metadata extension defines how the Item BO is displayed in Fiori Elements. Using annotations like <FONT face="courier new,courier"><a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1445379">@ui</a>.lineItem</FONT> and <FONT face="courier new,courier"><a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1445379">@ui</a>.Identification</FONT>, we specify which fields appear in the list report and object header. The&nbsp;<FONT face="courier new,courier"><a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1445379">@ui</a>.facet</FONT>&nbsp;groups the fields into a standard identification card. Placing these annotations in a metadata extension layer ensures <STRONG>Clean Core compliance</STRONG>, separating UI concerns from business logic, while enabling a ready-to-use Fiori preview.</P><P>After adding <STRONG>draft-enabled behavior</STRONG> and the <STRONG>metadata extension</STRONG>, let’s see the results in the Fiori preview:</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="17.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344567i3353399C54E11C23/image-size/large?v=v2&amp;px=999" role="button" title="17.png" alt="17.png" /></span></STRONG></P><P><STRONG>Create Button </STRONG>appears automatically at the top of the list report and clicking it opens a <STRONG>draft object</STRONG>, ready for entry.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="19.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344569i0C0FBDCF3D894E55/image-size/large?v=v2&amp;px=999" role="button" title="19.png" alt="19.png" /></span></P><P><STRONG>Delete Button&nbsp;</STRONG>appears at the top of the list report.</P><P><STRONG>List Report&nbsp;</STRONG>d<SPAN>isplays all annotated fields </SPAN><STRONG>without manually selecting columns</STRONG>, s<SPAN>hows all items.</SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="18.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/344568i72F6807AC55D6A1F/image-size/large?v=v2&amp;px=999" role="button" title="18.png" alt="18.png" /></span></SPAN></P><P><STRONG>Object Page: </STRONG>clicking a list entry opens the object page.</P><P><STRONG>Edit Button&nbsp;</STRONG>is visible on the object page, c<SPAN>licking it opens the draft for editing, supporting </SPAN><STRONG>safe modifications</STRONG><SPAN> before activation.</SPAN></P><P>This confirms that <STRONG>draft-enabled RAP objects</STRONG>, combined with <STRONG>metadata annotations</STRONG>, automatically generate a full-featured Fiori UI: list report, object page, and CRUD actions—<STRONG>all without writing UI code manually</STRONG>.</P><H1 id="toc-hId--1945340595">&nbsp;</H1><H1 id="toc-hId--2141854100">Part 3:&nbsp;Enhancing the Item BO with Actions, Determinations, Validations</H1><P>In Part 1 and Part 2, we created the basic structure of a RAP Business Object, enabled draft handling, activated CRUD operations, and prepared a clean UI using metadata extensions.</P><P>Now, in <STRONG>Part 3</STRONG>, we introduce the most important part of RAP:<BR /><STRONG>Business logic</STRONG> — implemented through:</P><UL><LI><P><STRONG>Validations</STRONG> (check before save)</P></LI><LI><P><STRONG>Determinations</STRONG> (auto-fill fields)</P></LI><LI><P><STRONG>Actions</STRONG> (custom operations triggered by the user)</P></LI><LI><P><STRONG>Side Effects</STRONG> (UI refresh logic after actions)</P></LI></UL><P>To demonstrate these features in a realistic scenario, we switch to a second simple Business Object:&nbsp;<STRONG>Leave Requests</STRONG></P><P>This BO includes fields such as employee name, requested days, and status.<BR />With it, we implement:</P><UL><LI><P>A validation to ensure the requested days are &gt; 0</P></LI><LI><P>A determination that sets the default status</P></LI><LI><P>A custom action <EM>Approve Leave Request</EM></P></LI><LI><P>Metadata annotations to show an action button in the UI</P></LI><LI><P>Side effects to refresh the UI automatically after approval</P></LI></UL><H2 id="toc-hId-1663196684"><STRONG>Leave Request BO — Behavior Definition</STRONG></H2><P>Here is the behavior definition, which we will explain piece by piece:</P><pre class="lia-code-sample language-abap"><code>managed implementation in class zbp_r_leavereq unique; strict ( 2 ); with draft; define behavior for ZR_LEAVEREQ persistent table zleavereq draft table zleavereq_d lock master total etag LastChangedAt authorization master ( instance ) etag master LastChangedAt { create ( authorization : global ); update; delete; field ( readonly, numbering : managed ) Leaveguid; draft action Activate optimized; draft action Edit; draft action Discard; draft action Resume; draft determine action Prepare { } validation checkDays on save { create; update; field DaysReq; } determination setDefaultStatus on modify { create; } action approveLeaveRequest; mapping for zleavereq { Leaveguid = leaveguid; EmployeeName = employee_name; DaysReq = days_req; Status = status; LocalCreatedAt = local_created_at; LocalCreatedBy = local_created_by; LocalLastChangedAt = local_last_changed_at; LocalLastChangedBy = local_last_changed_by; LastChangedAt = last_changed_at; } }</code></pre><H3 id="toc-hId-1173280172"><STRONG>Validation: checkDays</STRONG></H3><P>A <STRONG>validation</STRONG> allows you to stop a save operation if business rules are violated.</P><P>In this example, we ensure that requested days &gt; 0.</P><H3 id="toc-hId-976766667"><STRONG>Validation Logic in the Behavior Implementation Class</STRONG></H3><pre class="lia-code-sample language-abap"><code>METHOD checkDays. READ ENTITIES OF zr_leavereq IN LOCAL MODE ENTITY zr_leavereq ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(lt_leave_req). LOOP AT lt_leave_req ASSIGNING FIELD-SYMBOL(&lt;fs_lr&gt;). IF &lt;fs_lr&gt;-DaysReq &lt; 1. APPEND VALUE #( %tky = &lt;fs_lr&gt;-%tky ) TO failed-zr_leavereq. APPEND VALUE #( %tky = &lt;fs_lr&gt;-%tky %msg = new_message_with_text( text = 'Number of days should be &gt; 0.' severity = if_abap_behv_message=&gt;severity-error ) ) TO reported-zr_leavereq. ENDIF. ENDLOOP. ENDMETHOD.</code></pre><H3 id="toc-hId-780253162">What This Does</H3><UL><LI>Prevents invalid leave requests</LI><LI>Displays an error in the Fiori UI</LI><LI>Ensures data consistency</LI></UL><P>The validation is triggered on <STRONG>save</STRONG>, both for create and update.</P><H3 id="toc-hId-583739657"><STRONG>Determination: setDefaultStatus</STRONG></H3><P>A <STRONG>determination</STRONG> is used to auto-fill or derive values without UI involvement.</P><P>Here, whenever a leave request is created, we automatically set its initial status:</P><pre class="lia-code-sample language-abap"><code>METHOD setDefaultStatus. DATA(key) = VALUE #( keys[ 1 ] OPTIONAL ). MODIFY ENTITIES OF zr_leavereq IN LOCAL MODE ENTITY zr_leavereq UPDATE FIELDS ( Status ) WITH VALUE #( ( %tky = key-%tky Status = 'Pending' ) ). ENDMETHOD.</code></pre><H3 id="toc-hId-555409843"><STRONG>Action: approveLeaveRequest</STRONG></H3><P>Actions implement custom operations that the user triggers manually from the UI.</P><P>Here, we add an <STRONG>Approve</STRONG> action.</P><pre class="lia-code-sample language-abap"><code>METHOD approveLeaveRequest. DATA(key) = VALUE #( keys[ 1 ] OPTIONAL ). MODIFY ENTITIES OF zr_leavereq IN LOCAL MODE ENTITY zr_leavereq UPDATE FIELDS ( Status ) WITH VALUE #( ( %tky = key-%tky Status = 'Approved' ) ). ENDMETHOD.</code></pre><H3 id="toc-hId-358896338">When is an Action Appropriate?</H3><P>Use an action when:</P><UL><LI>&nbsp;you require manual user intent (approve, reject, submit)</LI><LI>&nbsp;the change differs from standard CRUD</LI><LI>&nbsp;you want a button in the UI<BR /><BR /></LI></UL><H3 id="toc-hId-162382833"><STRONG>Adding the Action to the Behavior Projection</STRONG></H3><P>Without adding it to the projection, the UI cannot call the action.</P><pre class="lia-code-sample language-abap"><code>projection; strict ( 2 ); use draft; define behavior for ZC_LEAVEREQ { use create; use update; use delete; use action approveLeaveRequest; side effects { action approveLeaveRequest affects $self, field Status; } use action Activate; use action Edit; use action Discard; use action Resume; use action Prepare; }</code></pre><H3 id="toc-hId--34130672"><STRONG>Side Effects — Keeping Fiori UI Updated</STRONG></H3><P>Side effects tell RAP <STRONG>which fields or entities might change</STRONG> when an action runs.</P><P>This ensures the UI refreshes automatically after the action is executed.</P><P>This informs Fiori Elements:</P><UL><LI><P>After pressing “Approve”, refresh the Status field</P></LI><LI><P>Update list report and object page automatically</P></LI></UL><P>Without side effects, the UI does not update until a manual refresh.</P><H3 id="toc-hId--230644177"><STRONG>Adding an Inline Action Button to the Fiori List Report</STRONG></H3><P><STRONG>In the Metadata Extension, you expose the action as a button:</STRONG></P><pre class="lia-code-sample language-abap"><code>@UI.lineItem: [{ position: 40, type: #FOR_ACTION, dataAction: 'approveLeaveRequest', label: 'Approve', inline: true }]</code></pre><H3 id="toc-hId--427157682">Meaning of inline: true</H3><P>✔ The approve button appears <STRONG>directly in the table row</STRONG><BR />✔ User can approve without navigating to the object page<BR />✔ Great for workflow-like processes</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="image.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350271i0BDEA75022524004/image-size/large?v=v2&amp;px=999" role="button" title="image.png" alt="image.png" /></span></P><P>&nbsp;</P><H1 id="toc-hId--36865173">Part 4: CDS Relationships: Associations and Composition</H1><P>In this part, we move to a more realistic RAP scenario, where our business object is no longer a single table.<BR />Instead, we have <STRONG>Projects</STRONG> and <STRONG>Tasks</STRONG>, and these objects need to be connected.</P><P>RAP uses <STRONG>CDS associations</STRONG> and <STRONG>compositions</STRONG> to model these relationships.</P><H2 id="toc-hId--526781685"><STRONG>CDS Associations — Linking Entities Together</STRONG></H2><P>An association is basically a <EM>link</EM> between two view entities — similar to a JOIN — but it is not executed until we actually navigate to it.</P><H3 id="toc-hId--1016698197"><STRONG>Association Between Task and User</STRONG></H3><P>In our app, each Task is assigned to a User.<BR />We represent this using an association:</P><pre class="lia-code-sample language-abap"><code>define view entity ZI_TASK as select from ztask_01 association [0..1] to ZR_USER as _User on _User.UserCode = $projection.Assignee {</code></pre><H3 id="toc-hId--1213211702"><STRONG>What this means (simple explanation)</STRONG></H3><UL><LI><P>association → create a link between Task and User</P></LI><LI><P>ZR_USER → the target entity (the User root)</P></LI><LI><P>_User → the name we will use to navigate to it</P></LI><LI><P>on ... → join condition ( Assignee equals the&nbsp;UserCode&nbsp;)</P></LI></UL><H2 id="toc-hId--948138509"><STRONG>Cardinality — What&nbsp;</STRONG>[0..1]<STRONG>&nbsp;Means</STRONG></H2><P>Cardinality describes <EM>how many related records</EM> the association can return.</P><P>This means:</P><UL><LI><P><STRONG>0</STRONG> → the task might not have an assigned user (Assignee is empty)</P></LI><LI><P><STRONG>1</STRONG> → if a user is assigned, there can be only one matching UserCode</P></LI></UL><P>This is a <STRONG>typical “optional 1-to-1”</STRONG> relationship.</P><P>If Assignee = 'USR01', we get that one user.<BR />If Assignee is empty, we get nothing.</P><P>&nbsp;</P><H2 id="toc-hId--1144652014"><STRONG>Using the Association in the Projection</STRONG></H2><P>Inside the projection view <CODE>ZC_TASK</CODE>, we read the user’s name through the <CODE>_User</CODE> association:</P><pre class="lia-code-sample language-abap"><code>_User.UserName as AssigneeName,</code></pre><P>This is only <EM>read</EM>, not stored anywhere in the Task table.</P><P>To make SAP Fiori show the text automatically, we add:</P><pre class="lia-code-sample language-abap"><code>@ObjectModel.text.element: ['AssigneeName'] Assignee,</code></pre><H3 id="toc-hId--1634568526">Result in the Fiori UI:</H3><UL><LI><P>The UI displays <STRONG>UserCode + UserName</STRONG><BR /><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="image.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350311iAA498D1E8747141E/image-size/medium?v=v2&amp;px=400" role="button" title="image.png" alt="image.png" /></span></STRONG></P></LI></UL><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><H1 id="toc-hId--1244276017">&nbsp;</H1><H1 id="toc-hId--1440789522">&nbsp;</H1><P>&nbsp;</P><P>&nbsp;</P><H2 id="toc-hId--1930706034">&nbsp;</H2><H2 id="toc-hId--2127219539"><STRONG>Why Associations Are Great</STRONG></H2><UL><LI><P>They avoid duplicate data</P></LI><LI><P>They allow “on-demand” navigation</P></LI><LI><P>They plug naturally into Fiori Elements<BR />(value helps, display texts, navigation links)</P></LI></UL><H2 id="toc-hId-1971234252"><STRONG>Composition — Building a Parent/Child Relationship (Project → Tasks)</STRONG></H2><P>Now that we’ve seen simple associations, let’s move to something more powerful in RAP:<BR /><STRONG>composition</STRONG>.</P><P>A composition is not just a link — it models a <STRONG>parent/child relationship</STRONG> where the child’s lifecycle depends entirely on the parent.</P><P>In our example:</P><UL><LI><P><STRONG>Project</STRONG> is the <EM>parent</EM></P></LI><LI><P><STRONG>Tasks</STRONG> are the <EM>children</EM></P></LI></UL><P>This is a very common RAP pattern used in real applications.</P><H1 id="toc-hId-2068123754"><STRONG>Defining the Composition in the Root Entity</STRONG></H1><P>In the Project root view (ZR_PROJECT), we define:</P><pre class="lia-code-sample language-abap"><code>composition [0..*] of ZI_TASK as _Tasks</code></pre><H3 id="toc-hId-1284804235">What this means (simple explanation):</H3><UL><LI><P>composition → strong parent–child relationship</P></LI><LI><P>[0..*] → a project can have <STRONG>zero, one, or many</STRONG> tasks</P></LI><LI><P>of ZI_TASK&nbsp;→ tasks are the child entity</P></LI><LI><P>_Tasks&nbsp;→ the navigation property we will use in the UI</P></LI></UL><P>This tells RAP that:</P><P>&nbsp;Tasks belong to a project<BR />&nbsp;Tasks cannot exist without the project<BR />&nbsp;If the project is deleted, all its tasks must be deleted too<BR />&nbsp;Tasks must always reference a ProjectId (its parent)</P><P>This is different from a normal association — it defines <STRONG>ownership</STRONG>.</P><H1 id="toc-hId-1843280435"><STRONG>Exposing the Composition in the Projection</STRONG></H1><P>In the Project projection (ZC_PROJECT), we expose the composition:</P><pre class="lia-code-sample language-abap"><code>_Tasks : redirected to composition child ZC_TASK</code></pre><P>This allows the UI to show <STRONG>the list of Tasks inside the Project object page</STRONG>, including:</P><UL><LI><P>Create Task</P></LI><LI><P>Edit Task</P></LI><LI><P>Delete Task</P></LI></UL><P>All directly in the Project UI.</P><P>Without this redirection, the Tasks table wouldn't appear in the Fiori Elements app.</P><H1 id="toc-hId-1646766930"><STRONG>Behavior Definition: Root and Child Must Work Together</STRONG></H1><P>Since compositions define hierarchy, the <STRONG>behavior</STRONG> must reflect that hierarchy.</P><pre class="lia-code-sample language-abap"><code>define behavior for ZR_PROJECT alias Project { create; update; delete; association _Tasks { create; with draft; } }</code></pre><H3 id="toc-hId-863447411">Meaning:</H3><UL><LI><P>The Project behavior controls the entire object</P></LI><LI><P>It is allowed to <STRONG>create children</STRONG> (_Tasks { create; })</P></LI><LI><P>Children are created <STRONG>in the context of the parent</STRONG></P></LI></UL><P>In Fiori:</P><UL><LI><P>When you open a Project → Task table appears</P></LI><LI><P>“Create” inside the Tasks table creates a <STRONG>child</STRONG> of this project</P></LI></UL><pre class="lia-code-sample language-abap"><code>define behavior for ZI_TASK alias Task { update; delete; field (readonly) ParentId; association _Project { with draft; } }</code></pre><H3 id="toc-hId-666933906">Meaning:</H3><UL><LI><P>Tasks cannot create their own parent</P></LI><LI><P>Tasks inherit locking and authorization from the Project</P></LI><LI><P>Tasks cannot change the ParentId (because it is read-only)</P></LI></UL><P>The lifecycle looks like this:</P><UL><LI><P>You create a <STRONG>Project</STRONG></P></LI><LI><P>Inside the project, you add <STRONG>Tasks</STRONG></P></LI><LI><P>Tasks cannot exist outside the Project</P></LI></UL><H2 id="toc-hId-763823408">Why Composition Is Important</H2><P>It gives RAP a clear structure of your data model<BR />It enables nested object pages (Projects → Tasks)<BR />It simplifies locking, authorization, and lifecycle management<BR />Fiori Elements automatically understands parent/child UI patterns<BR />Child objects cannot “float” or become inconsistent</P><P>&nbsp;</P><H1 id="toc-hId-860712910">Part 5: Value Helps&nbsp;</H1><P>So far, we built our entities, associations, and composition.<BR />But in a real Fiori Elements app, users shouldn’t manually type in IDs.</P><P>Instead, they should select values from a <STRONG>value help</STRONG> (similar to a search help in classical ABAP).</P><P>In RAP, value helps are implemented using <STRONG>CDS view entities</STRONG> and the annotation:</P><pre class="lia-code-sample language-abap"><code>@Consumption.valueHelpDefinition</code></pre><H2 id="toc-hId-370796398"><STRONG>Creating a Value Help View</STRONG></H2><P>Let’s look at the value help for selecting a User.</P><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Value Help for User' @Metadata.ignorePropagatedAnnotations: true define view entity ZI_USER_VH as select from ZR_USER { @UI.hidden: true key UserId, UserCode, UserName }</code></pre><UL><LI><P>It selects from ZR_USER, our user root entity.</P></LI><LI><P>The value help will show <STRONG>UserCode</STRONG> and <STRONG>UserName</STRONG> in the popup search dialog.</P></LI><LI><P>This view is not a projection — it's a standalone VH definition recommended for RAP apps.</P></LI></UL><P>This view is now ready to be used by any field that needs a value help for Users.</P><H2 id="toc-hId-174282893"><STRONG>Plugging the Value Help into the Task Projection</STRONG></H2><P>In the Task projection, we attach the value help to the <STRONG>Assignee</STRONG> field:</P><pre class="lia-code-sample language-abap"><code>@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_USER_VH', element: 'UserCode' }, useForValidation: true }] Assignee,</code></pre><H3 id="toc-hId--315633619">What this does:</H3><P>Opens a value help popup<BR />Shows columns from ZI_USER_VH (UserCode, UserName)<BR />Ensures the selected UserCode is valid (useForValidation: true)<BR />Prevents users from entering invalid users</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350318i31B6B3B8D50B2471/image-size/large?v=v2&amp;px=999" role="button" title="image.png" alt="image.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P> 2025-11-28T12:18:20.855000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/how-to-write-table-function-in-stranded-way-like-sap/ba-p/14279530 How to write Table function in stranded way like SAP 2025-12-09T12:36:55.534000+01:00 Krithik https://community.sap.com/t5/user/viewprofilepage/user-id/1398143 <P>How to Write CDS Table Functions the Standard SAP Way</P><P>In SAP S/4HANA, we cannot always express complex business logic using pure CDS syntax. To manage scenarios like long text processing, procedural calculations, or important joins, SAP uses CDS Table Functions implemented through AMDP.</P><P>While many developers create table functions on the fly, SAP sticks to a strict and consistent design pattern across its standard content. This approach ensures good performance, readability, upgrade safety, and transportability.</P><P>A useful way to grasp this standard is to look at how SAP builds transactional CDS views, especially those that use CDS Table Functions. By examining SAP-delivered objects like I_SalesOrderTP, we can clearly see the structure, naming conventions, annotations, and implementation method that SAP expects developers to follow.</P><P>This guide explains how SAP writes table functions, how they implement them using AMDP, and how they use them in CDS views. This will help you design your own extensions in the same way SAP does.</P><OL><LI><STRONG>Start with a Standard View: I_SALESORDERTP</STRONG>.</LI></OL><UL><LI>SAP provides many standard CDS views in S/4HANA.</LI><LI>To understand how SAP writes table functions, the easiest example is the view: I_SALESORDERTP</LI><LI>This is a Transactional Processing View, delivered by SAP.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="2025-11-27_19h51_30.png" style="width: 795px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/346206i2E91480425C8A436/image-dimensions/795x410?v=v2" width="795" height="410" role="button" title="2025-11-27_19h51_30.png" alt="2025-11-27_19h51_30.png" /></span></P><P>&nbsp; &nbsp;2.&nbsp;<STRONG>Locate the Table Function Used Inside the View.</STRONG></P><UL><LI>Inside the view, you will notice SAP has used: <STRONG>with parameters (...).</STRONG></LI></UL><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="2025-11-27_19h53_17.png" style="width: 808px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/346207i528B8200465E6E01/image-dimensions/808x418?v=v2" width="808" height="418" role="button" title="2025-11-27_19h53_17.png" alt="2025-11-27_19h53_17.png" /></span></STRONG></P><UL><LI>This indicates that the view is consuming <STRONG>a CDS Table Function</STRONG>.</LI></UL><P><STRONG>&nbsp; &nbsp; &nbsp; &nbsp; 3. You will find the CDS Table Function that SAP has written.</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="2025-11-27_19h53_23.png" style="width: 822px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/346208iA28B1A25D2DA4845/image-dimensions/822x425?v=v2" width="822" height="425" role="button" title="2025-11-27_19h53_23.png" alt="2025-11-27_19h53_23.png" /></span></STRONG></P><P><STRONG>&nbsp; &nbsp; 4.&nbsp; Open the AMDP Class to See SAP’s Logic.</STRONG></P><UL><LI>Once you find the Table Function name, open the AMDP class: <STRONG>cl_sd_S4h_stxl_utils=&gt;get_header_text</STRONG></LI><LI>Inside this class, SAP has written the entire logic.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="2025-11-27_19h53_43.png" style="width: 530px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/346209iFF5F548747352D63/image-dimensions/530x479?v=v2" width="530" height="479" role="button" title="2025-11-27_19h53_43.png" alt="2025-11-27_19h53_43.png" /></span></P><P>When crafting Table Functions ", in the manner SAP does " consistently adhere to this structure:</P><P>Create a CDS Table Function with parameters.</P><P>Implement it via an AMDP class/method using native SQLScript.</P><P>Consume it in your final CDS view using with parameters.</P><P>Follow the exact naming, annotation, and structure shown in standard objects such as I_SalesOrderTP, I_PurchaseOrderTP, I_BillingDocumentTP, etc.</P><P>Following this pattern guarantees:</P><P>Best performance (native HANA execution)</P><P>Transportability and upgrade-safety</P><P>Consistency with thousands of standard SAP-delivered objects<BR /><BR /></P><P>Conclusion</P><P>It is a tried-and-true architectural best practice to use SAP's standard pattern for CDS Table Functions. You can align your custom developments with the same design principles used in core SAP objects like *I_SalesOrderTP*, *I_PurchaseOrderTP*, and *I_BillingDocumentTP* by defining a CDS Table Function with parameters, implementing its logic in an AMDP method using native SQLScript, and consuming it through a final CDS view.</P><P><BR />This method guarantees that sophisticated logic runs directly on SAP HANA for maximum efficiency, stays neatly isolated from the consumption layer, and is resilient to upgrades and transports. More significantly, because it adheres to a well-known and extensively used standard, it makes your solution instantly comprehensible to other SAP developers.</P><P>&nbsp;</P><P>&nbsp;</P> 2025-12-09T12:36:55.534000+01:00 https://community.sap.com/t5/abap-blog-posts/collective-value-helps-in-rap-v2-and-v4-implementation-guide-part-2/ba-p/14286757 Collective Value Helps in RAP: V2 and V4 Implementation Guide - Part 2 2025-12-09T15:35:14.655000+01:00 Abhinav_Roy https://community.sap.com/t5/user/viewprofilepage/user-id/1109 <P><SPAN>In <A href="https://community.sap.com/t5/abap-blog-posts/collective-value-helps-in-rap-v2-and-v4-implementation-guide-part-1/ba-p/14271885" target="_blank">Part 1</A>&nbsp;of this series, we explored the fundamentals of <STRONG>Collective Value Helps</STRONG> in RAP, covering implementation patterns across OData V2 and V4 service bindings. The community response has been overwhelming, with particular interest in hierarchical implementations for complex business scenarios.</SPAN></P><P><SPAN>While CDS hierarchies are extensively documented in the SAP ecosystem and widely used for representing parent-child relationships across business objects, a critical implementation gap exists: <STRONG>there are virtually no practical examples of incorporating hierarchical display patterns within Collective Value Helps.</STRONG> <STRONG>Part 2</STRONG> bridges this gap by demonstrating how to seamlessly integrate hierarchical search templates into the collective value help framework we built in Part 1.<BR /><BR /></SPAN><SPAN><STRONG>Watch the demonstration video below</STRONG> to see hierarchical value helps in action, including how they work alongside existing flat list search templates, in a Collective Value Help:<BR /><BR /><div class="video-embed-center video-embed"><iframe class="embedly-embed" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F2Zt9gykfJOE%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D2Zt9gykfJOE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F2Zt9gykfJOE%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="400" height="225" scrolling="no" title="SAP Community Hierarchical Variant - CVH" frameborder="0" allow="autoplay; fullscreen; encrypted-media; picture-in-picture;" allowfullscreen="true"></iframe></div><BR /></SPAN></P><P><FONT color="#339966"><U><SPAN>System Requirements</SPAN></U></FONT></P><P><FONT color="#339966"><EM>**Hierarchical Value Help Dialogs require: **</EM></FONT></P><P><FONT color="#339966"><EM>**SAP S/4HANA Cloud**<BR /></EM><EM>--Minimum Release: 2311<BR /></EM><EM>--Protocol: OData V4 service binding</EM></FONT></P><P><FONT color="#339966"><EM>**SAP S/4HANA On-Premise/Private Edition: **<BR /></EM><EM>--Minimum Release : S/4HANA 2025 onwards<BR /></EM><EM>--Protocol: OData V4 service binding</EM></FONT></P><P><FONT color="#339966"><EM>**Important: ** OData V2 does not support hierarchical</EM> visualization&nbsp;<EM>out of the box via CDS Hierarchy due to protocol limitations. CDS hierarchical patterns require OData V4.</EM></FONT></P><P><STRONG>CDS Hierarchies: Foundation for Hierarchical Value Helps</STRONG></P><P>CDS (Core Data Services) hierarchies are well-established patterns in the SAP landscape for representing parent-child relationships. SAP provides comprehensive documentation and numerous community resources for learning hierarchy fundamentals:</P><UL><LI><SPAN><A href="https://help.sap.com/docs/abap-cloud/abap-data-models/hierarchy-definition" target="_blank" rel="noopener noreferrer">Hierarchy Definition | SAP Help Portal</A></SPAN></LI><LI><SPAN><A href="https://help.sap.com/docs/abap-cloud/abap-rap/treeview-with-read-only-capability?version=sap_btp" target="_blank" rel="noopener noreferrer">Treeviews with Read-Only Capabilities | SAP Help Portal</A></SPAN></LI><LI><A href="https://community.sap.com/t5/technology-blog-posts-by-sap/cds-how-to-define-hierarchy-view/ba-p/13758059" target="_self">SAP Community: CDS Hierarchy Articles</A></LI></UL><P><STRONG>This article focuses specifically on utilizing CDS hierarchies within RAP-compliant value helps</STRONG> and demonstrating how to incorporate hierarchical search templates alongside the flat templates created in Part 1.</P><P><STRONG>Key Use Case:</STRONG> Hierarchies are particularly powerful in domains like Asset Management, where technical objects form complex parent-child structures that users need to navigate when making selections.</P><P><STRONG>Business Context: Asset Management-&gt; Hierarchical Relationships</STRONG></P><P>In Asset Management, technical objects naturally form hierarchical structures that reflect real-world installations and organizational relationships:</P><P><STRONG>Functional Location Hierarchies:</STRONG></P><UL><LI>Parent functional locations contain child functional locations</LI><LI>Example: TATM → TATM-UT3 → TATM-UT3-001</LI><LI>Represents physical plant structure and organizational grouping</LI></UL><P><STRONG>Equipment Hierarchies:</STRONG></P><UL><LI>Equipment can be installed under functional locations</LI><LI>Equipment can be installed under other equipment (sub-assemblies)</LI><LI>Example: Main equipment (11947458) contains sub-equipment (11947627)</LI></UL><P><STRONG>Mixed Hierarchies:</STRONG></P><UL><LI>Equipment installed at functional locations</LI><LI>Sub-equipment installed under main equipment</LI><LI>Creates complex parent-child navigation <SPAN>requirements</SPAN></LI></UL><P><SPAN>A sample Hierarchy in Asset Management:<BR /></SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Transaction: IH01 - Structure List" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350113i6B449DCB4E2430AE/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_0-1765275145771.png" alt="Transaction: IH01 - Structure List" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Transaction: IH01 - Structure List</span></span></P><P><STRONG>Why Hierarchical Value Helps Matter:</STRONG></P><P>When users select technical objects in business processes (work orders, maintenance notifications, asset transfers), they need to:</P><UL><LI>Understand the installation hierarchy</LI><LI>Navigate parent-child relationships visually</LI><LI>Select objects while seeing their organizational context</LI><LI>Identify relationships between equipment and functional locations</LI></UL><P>Standard flat list value helps lose this critical hierarchical context, making object selection difficult and error-prone in complex asset structures.</P><P><SPAN>Implementation: Building the Hierarchical VDM Model </SPAN></P><P><STRONG>Step 1: Interface View (I-View) with Parent Association</STRONG></P><P>The foundation of any CDS hierarchy is a self-association that establishes the parent-child relationship.<BR /><BR /></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="I-View" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350176i90BA3A7BE43AA7E5/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_0-1765276862163.png" alt="I-View" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">I-View</span></span></P><P><STRONG>Critical Elements:</STRONG></P><UL><LI><STRONG>Self-Association _ParentNode:</STRONG> Establishes the many-to-one parent relationship</LI><LI><STRONG>Cardinality [0..1]:</STRONG> Each node has either zero (root) or one parent</LI><LI><STRONG>Join Condition:</STRONG> Links child's SuperiorTechnicalObject to parent's TechnicalObject</LI></UL><P>This I-View serves as the data foundation, providing the parent-child relationship that the hierarchy view will consume.</P><P><STRONG>Step 2: Hierarchy View Definition</STRONG></P><P>The hierarchy view transforms the I-View's parent association into an actual hierarchical structure with defined traversal rules.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Hierarchy View" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350177i06598EFF9C04E570/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_1-1765276926694.png" alt="Hierarchy View" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Hierarchy View</span></span></P><P><STRONG>Critical Hierarchy Annotations:</STRONG></P><OL><LI><STRONG>source ZAR_I_TechObjHierarchy:</STRONG> References the I-View containing the parent association</LI><LI><STRONG>child to parent association _ParentNode:</STRONG> Specifies which association defines the hierarchy</LI><LI><STRONG>start where SuperiorTechnicalObject is initial:</STRONG> Defines root nodes (no parent = top of hierarchy)</LI><LI><STRONG>siblings order by TechnicalObject:</STRONG> Sorts nodes at the same level</LI><LI><STRONG>multiple parents not allowed:</STRONG> Enforces strict tree structure (each node has max one parent)</LI></OL><P>This hierarchy view establishes the traversal logic and structural rules for displaying the parent-child relationships.</P><P>&nbsp;</P><P><STRONG>Step 3: Consumption (C-View) Definition&nbsp;</STRONG></P><P>The consumption view serves as the bridge between the CDS hierarchy and the collective value help framework. It exposes the hierarchy as a searchable value help provider while maintaining the hierarchical data structure.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="C-View" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350178i1A66EA4BBEADFDAB/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_2-1765277179651.png" alt="C-View" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">C-View</span></span></P><P><STRONG>Critical Annotations:<BR /></STRONG></P><OL><LI><STRONG>@ObjectModel.supportedCapabilities</STRONG><BR /><STRONG>#VALUE_HELP_PROVIDER</STRONG>: Enables this view to provide value help data<BR /><STRONG>#SEARCHABLE_ENTITY</STRONG>: Allows search functionality within the value help dialog<BR />These capabilities are essential for user interaction</LI><LI><STRONG><a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1599241">@odata</a>.hierarchy.recursiveHierarchy: [{ entity.name: 'ZAR_I_TechObjHierarchyView' }]</STRONG><BR />THE CRITICAL HIERARCHICAL LINK<BR /><STRONG>Note:</STRONG> The entity name should reference the <STRONG>Hierarchy View</STRONG> (from Step 2), not the I-View or C-View itself.<BR />Points to the CDS hierarchy view created in Step 2<BR />Instructs OData V4 service to use hierarchical structure<BR />Without this annotation, hierarchy won't display in value help</LI><LI><STRONG>association of many to one ... as _ParentNode</STRONG><BR />Recreates the parent association in the consumption layer<BR />Must match the join conditions from the I-View<BR />Required for OData V4 hierarchy metadata generation<BR />Links both TechnicalObject AND TechObjIsEquipOrFuncnLoc (composite key)</LI></OL><P><STRONG><BR />Step 4: Including Hierarchical Template in Collective Value Help<BR /><BR /></STRONG>Now we integrate the hierarchical search template into our existing collective value help framework from Part 1:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="CVH V2 Metadata Extension" style="width: 742px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350276iA574D0E8B7D628A7/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_0-1765284016068.png" alt="CVH V2 Metadata Extension" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">CVH V2 Metadata Extension</span></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="CVH V4 Metadata Extension" style="width: 785px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350277i534D6BAD5BEC6D23/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_1-1765284037633.png" alt="CVH V4 Metadata Extension" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">CVH V4 Metadata Extension</span></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Service Definition" style="width: 698px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350278iAF30882ADD5E2AB7/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_2-1765284142136.png" alt="Service Definition" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Service Definition</span></span></P><P><STRONG>OData V2 Service Binding: The Limitation</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Service Binding OData V2" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350279i5E8C2D9DE435F840/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_3-1765284199980.png" alt="Service Binding OData V2" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Service Binding OData V2</span></span></P><P><STRONG>This eliminates the possibility of incorporating hierarchical search templates via CDS hierarchy in V2 collective value helps.</STRONG> OData V2's protocol limitations prevent hierarchy visualization in value help dialogs</P><P><STRONG><BR />OData V4 Service Binding: The Solution Path</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Service Binding OData V4" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350280i61F5F556EF135F3C/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_0-1765284407687.png" alt="Service Binding OData V4" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Service Binding OData V4</span></span></P><P>The V4 service binding successfully exposes the hierarchical template without errors.</P><H3 id="toc-hId-1895640971"><BR />The Problem - Flat List Display</H3><P class="">Even with a properly defined hierarchy view exposed in V4, the initial preview reveals an unexpected result:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Flat List Display (as opposed to expected Hierarchical display)" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350282i95E36C0C3779F7B5/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_1-1765284477750.png" alt="Flat List Display (as opposed to expected Hierarchical display)" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Flat List Display (as opposed to expected Hierarchical display)</span></span></P><P class=""><STRONG><BR />The Problem:<BR /></STRONG><SPAN>Despite having a hierarchical CDS view, the value help displays data as a </SPAN><STRONG>flat list</STRONG><SPAN> without any parent-child visualization. Users see individual records but lose all hierarchical context.</SPAN></P><P class=""><STRONG>Why This Happens:<BR /></STRONG><SPAN>Creating a CDS hierarchy view is necessary but </SPAN><STRONG>not sufficient</STRONG><SPAN> for hierarchical display in value helps. The RAP framework requires <EM>explicit UI presentation instructions</EM> to render hierarchy in the value help dialog.</SPAN></P><P class=""><STRONG>The Missing Piece:</STRONG> The framework needs explicit instructions via presentation variant annotations to understand that this data should be rendered as a hierarchy tree, not a flat table. Without these annotations, OData V4 treats the hierarchy view as just another data source.<BR /><BR /><STRONG>The Solution - Presentation Variant Annotations</STRONG><BR />To provision hierarchical display in value helps, we must add specific presentation variant annotations that declare hierarchical visualization intent.<BR /><BR /><U>Consumption View (C-View) Annotations</U></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="C-View (Presentation Variant Added)" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350296i16DB4408E668ECBE/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_0-1765284859373.png" alt="C-View (Presentation Variant Added)" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">C-View (Presentation Variant Added)</span></span></P><P>A presentation variant annotation needs to be included here which will contain the InitialExpansionLevel for the hierarchy and&nbsp; a property RecursiveHierarchyQualifier.</P><P class=""><STRONG>RecursiveHierarchyQualifier</STRONG> - This annotation contains a string with the name of the hierarchy view and make possible that the data is then shown on UI as tree table. The projection view should also have the annotation<BR /><BR /><SPAN><STRONG>InitialExpansionLevel</STRONG> - This annotation indicates up to which level a display hierarchy shall be initially expanded.</SPAN><BR /><BR /><U>Collective Value Help Metadata Extension</U></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="CVH V4 Metadata Extension (Presentation Variant annotation added)" style="width: 668px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350312i4D5761FE4F127D32/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_0-1765285284629.png" alt="CVH V4 Metadata Extension (Presentation Variant annotation added)" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">CVH V4 Metadata Extension (Presentation Variant annotation added)</span></span></P><P>A <SPAN><STRONG>presentationVariantQualifier</STRONG> annotation needs to be included here, which should've the same value as the Qualifier in the C-View, i.e., '<STRONG>HIERARCHY</STRONG>', in this case. This annotation&nbsp;indicates how the value help result should be displayed.<BR /><BR /></SPAN></P><P><SPAN><STRONG>The Result: Hierarchical Value Help in Action</STRONG><BR /></SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Hierarchical value help display" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/350315i8BC8724DE1A9A35B/image-size/large?v=v2&amp;px=999" role="button" title="Abhinav_Roy_1-1765285480130.png" alt="Hierarchical value help display" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Hierarchical value help display</span></span></P><P><STRONG><U>Success! The hierarchical variant now displays</U></STRONG>:</P><UL><LI>Parent-child relationships visualized as tree structure</LI><LI>Expand/collapse controls for navigation</LI><LI>Indentation showing hierarchy levels</LI><LI>Seamless integration with flat templates from Part 1</LI><LI>Full hierarchy traversal in value help dialog</LI></UL><P><STRONG><U>User Experience - End Users can now</U></STRONG>:</P><UL><LI>Switch between flat and hierarchical search templates</LI><LI>Navigate parent-child relationships visually</LI><LI>Expand/collapse hierarchy nodes and even the entire Tree View</LI><LI>Select objects while understanding their organizational context</LI><LI>See equipment installation hierarchies and functional location structures</LI></UL><P><FONT size="5"><STRONG>Key Takeaways: When to Use Hierarchical Collective Value Helps<BR /></STRONG></FONT><BR /><U><STRONG>Use Hierarchical Patterns When</STRONG></U>:</P><UL><LI>Parent-Child Relationships Matter: Business objects naturally form hierarchies (org structures, location hierarchies etc)</LI><LI>Context Aids Selection: Users need to see relationships to make correct selections</LI><LI>Navigation is Important: Users need to browse up/down hierarchies during selection</LI><LI>OData V4 is Available: V2 protocol does not support hierarchy visualization</LI></UL><P><U><STRONG>Implementation Checklist</STRONG></U>:</P><UL><LI>Define I-View with self-association (_ParentNode)</LI><LI>Create hierarchy view with traversal rules (start where, siblings order by)</LI><LI>Use OData V4 service binding (V2 not supported)</LI><LI>Add presentation variant in C-View</LI><LI>Reference presentation variant in CVH metadata extension</LI><LI>Test expand/collapse and hierarchy navigation</LI></UL><P><U><STRONG>Key Implementation points</STRONG></U>:</P><UL><LI>Cardinality Enforcement: multiple parents not allowed ensures tree structure</LI><LI>Root Node Definition: start where clause correctly identifies top-level nodes</LI><LI>Presentation Variant annotation must be added in&nbsp;C-View and CVH metadata</LI><LI>Qualifier Consistency: Same qualifier in C-View and CVH metadata</LI></UL><P><BR /><FONT size="5"><STRONG>Series Conclusion</STRONG></FONT><BR />This two-part series has explored the complete spectrum of collective value helps in RAP:<BR /><STRONG><U>Part 1 established the foundation</U></STRONG>:</P><OL><LI>Basic collective value help concepts and structure</LI><LI>Implementation across OData V2 and V4 service bindings</LI><LI>Service binding architectural differences</LI><LI>Nested value help workarounds</LI><LI>Multi-dimensional search capabilities</LI></OL><P><STRONG><U>Part 2 extended to advanced patterns</U></STRONG>:</P><OL><LI>Hierarchical CDS view construction</LI><LI>VDM model for hierarchy-enabled value helps</LI><LI>OData V2 protocol limitations</LI><LI>Presentation variant configuration for hierarchy visualization</LI><LI>Seamless integration of flat and hierarchical search templates</LI></OL><P>Together, these patterns enable user-centric, multi-criteria search capabilities that leverage RAP's full value help framework while maintaining clean architectural separation and reusability.</P><P><STRONG>Key Architectural Insight</STRONG>:<BR />Collective value helps in RAP provide a powerful, user-centric approach to value help management by enabling multi-criteria search through a single, reusable model. The addition of hierarchical display patterns extends this capability to complex business scenarios requiring parent-child navigation—delivering a comprehensive search experience that adapts to diverse user needs.<BR /><BR /><FONT size="5"><STRONG>Conclusion</STRONG></FONT><BR />Hierarchical collective value helps represent the convergence of RAP's value help framework with CDS hierarchy capabilities, enabling rich, context-aware search experiences for complex business objects. While implementation requires careful attention to presentation variant configuration and V4 protocol requirements, the result is a powerful pattern applicable across any SAP domain where parent-child relationships drive user decision-making.<BR />Whether you're building asset management applications, organizational hierarchies, material master navigation, or any scenario requiring hierarchical context during selection, this pattern provides the foundation for delivering intuitive, efficient user experiences.<BR />The combination of CDS hierarchies, collective value helps, and RAP's presentation variant framework creates a powerful combination for solving complex data selection challenges-no custom coding required, just optimal usage of key annotations.<BR />Thank you for following this two-part series. I welcome your feedback, and experiences implementing collective value helps in your own RAP applications.</P> 2025-12-09T15:35:14.655000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/how-to-create-a-btp-account-and-add-in-the-adt/ba-p/14079215 How to create a BTP Account and add in the ADT 2025-12-12T08:59:14.528000+01:00 Krithik https://community.sap.com/t5/user/viewprofilepage/user-id/1398143 <P><SPAN>If you are new to SAP Business Technology Platform (BTP) or planning to explore ABAP Cloud development, creating an SAP BTP Trial account is the perfect place to start. The SAP BTP Trial allows you to experiment with SAP services, build applications, and practice ABAP Cloud development free of cost and without any commercial commitment. In this blog, I will walk you through step-by-step instructions to create an SAP BTP Trial account and connect it to ABAP Development Tools (ADT) in Eclipse.</SPAN></P><P>&nbsp;</P><P><STRONG>Step 1: Visit SAP’s Website</STRONG></P><UL><LI>Go to&nbsp;&nbsp;<A href="http://www.sap.com/" target="_blank" rel="noopener noreferrer">www.sap.com</A>.</LI><LI>Find the <STRONG>“Free Trial”</STRONG>&nbsp;and click on it .</LI><LI><STRONG>Start your free trial&nbsp;</STRONG>&nbsp;will be there click on it.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="image.png" style="width: 544px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/351233i334C81C87678D2D5/image-dimensions/544x265/is-moderation-mode/true?v=v2" width="544" height="265" role="button" title="image.png" alt="image.png" /></span></P><P><STRONG>Step 2: Sign Up or Log In</STRONG></P><UL><LI><STRONG>New?</STRONG> Click <STRONG>“Register”</STRONG>:</LI><UL><LI>Enter your email and login.</LI></UL></UL><P><STRONG>Step 3: Create Your Trial</STRONG></P><UL><LI>On the <STRONG>“Welcome”</STRONG> page, click <STRONG>“Go to Your Trial Account”</STRONG>.</LI><LI>Pick a region which is close to you.</LI></UL><P>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="Krithik_1-1744898750063.png" style="width: 251px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252136i7E66DBCA12C2E814/image-dimensions/251x225?v=v2" width="251" height="225" role="button" title="Krithik_1-1744898750063.png" alt="Krithik_1-1744898750063.png" /></span><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Krithik_2-1744898750064.png" style="width: 249px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252135iD8A01406FEFCAC42/image-dimensions/249x223?v=v2" width="249" height="223" role="button" title="Krithik_2-1744898750064.png" alt="Krithik_2-1744898750064.png" /></span></P><UL><LI>Click <STRONG>“Create Account”</STRONG>&nbsp;.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_3-1744898750069.png" style="width: 508px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252139iAD5B94B278671AA1/image-dimensions/508x259?v=v2" width="508" height="259" role="button" title="Krithik_3-1744898750069.png" alt="Krithik_3-1744898750069.png" /></span></P><P><STRONG>Step 4: Explore Your Playground</STRONG></P><UL><LI>Click the <STRONG>“trial”</STRONG> box to start.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_4-1744898750070.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252138i44D85801CE95B957/image-size/medium?v=v2&amp;px=400" role="button" title="Krithik_4-1744898750070.png" alt="Krithik_4-1744898750070.png" /></span></P><P>&nbsp;</P><UL><LI>Check out <STRONG>“Service Marketplace”</STRONG> for fun tools like app-building.</LI></UL><P><STRONG>Step 5: Enter Your Playground</STRONG></P><UL><LI>You’re in the <STRONG>SAP BTP Cockpit</STRONG>&nbsp;Now.<span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_5-1744898750075.png" style="width: 506px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252140i74881D5EF2AC6FD5/image-dimensions/506x244?v=v2" width="506" height="244" role="button" title="Krithik_5-1744898750075.png" alt="Krithik_5-1744898750075.png" /></span></LI></UL><P><STRONG>Step 6: Start Your ABAP Trial</STRONG></P><UL><LI>click <STRONG>“Boosters”</STRONG>&nbsp;</LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_6-1744898750081.png" style="width: 535px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252144i728B1376C10F3317/image-dimensions/535x261?v=v2" width="535" height="261" role="button" title="Krithik_6-1744898750081.png" alt="Krithik_6-1744898750081.png" /></span><STRONG>“Prepare an Account for ABAP Trial”</STRONG>&nbsp;--&gt;&nbsp;<STRONG>“Start”</STRONG>.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_7-1744898750082.png" style="width: 541px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252142i0EAAC3879E654D20/image-dimensions/541x263?v=v2" width="541" height="263" role="button" title="Krithik_7-1744898750082.png" alt="Krithik_7-1744898750082.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_8-1744898750083.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252141i919FC0485C8CA1B2/image-size/medium?v=v2&amp;px=400" role="button" title="Krithik_8-1744898750083.png" alt="Krithik_8-1744898750083.png" /></span></P><UL><LI>A pop-up says, <STRONG>“Successful Booster Executed” And click</STRONG>&nbsp;<STRONG>“Go to Service Key”</STRONG>.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_9-1744898750084.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252145i71707FA9E74E99B5/image-size/medium?v=v2&amp;px=400" role="button" title="Krithik_9-1744898750084.png" alt="Krithik_9-1744898750084.png" /></span></P><P>&nbsp;</P><UL><LI>Find the <STRONG>Service Key</STRONG> row, click the <STRONG>3 dots</STRONG>, and select <STRONG>“View”</STRONG>.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_10-1744898750091.png" style="width: 539px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252146i04FC28E32C6AED88/image-dimensions/539x260?v=v2" width="539" height="260" role="button" title="Krithik_10-1744898750091.png" alt="Krithik_10-1744898750091.png" /></span></P><P>&nbsp;</P><UL><LI>Copy the <STRONG>JSON code</STRONG>.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_11-1744898750100.png" style="width: 530px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252147i846D2CC3D509792A/image-dimensions/530x282?v=v2" width="530" height="282" role="button" title="Krithik_11-1744898750100.png" alt="Krithik_11-1744898750100.png" /></span></P><P><STRONG>Step 7: Set Up Eclipse</STRONG></P><UL><LI>Open <STRONG>Eclipse</STRONG>&nbsp;In your system.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_12-1744898750103.png" style="width: 535px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252148i331865E07BAB9D6E/image-dimensions/535x294?v=v2" width="535" height="294" role="button" title="Krithik_12-1744898750103.png" alt="Krithik_12-1744898750103.png" /></span></P><UL><LI>Click <STRONG>“File” --&gt; “New” --&gt; “Project”--&gt;</STRONG>&nbsp;<STRONG>“ABAP Cloud Project”</STRONG>.</LI><LI>Paste the JSON code.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_13-1744898750105.png" style="width: 478px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252150i3E4ABB127557846C/image-dimensions/478x362?v=v2" width="478" height="362" role="button" title="Krithik_13-1744898750105.png" alt="Krithik_13-1744898750105.png" /></span></P><P><STRONG>Step 8: Create Your Coding Project</STRONG></P><UL><LI>See <STRONG>“Successfully Logged On” On the Browser&nbsp;</STRONG></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_14-1744898750106.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252149iF9D9CCCBC5D0672C/image-size/medium?v=v2&amp;px=400" role="button" title="Krithik_14-1744898750106.png" alt="Krithik_14-1744898750106.png" /></span></P><P>&nbsp;</P><UL><LI><SPAN>In Eclipse, your project appears on the left.</SPAN></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Krithik_16-1744898750110.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/252151iA292CBF35D2E2A3B/image-size/medium?v=v2&amp;px=400" role="button" title="Krithik_16-1744898750110.png" alt="Krithik_16-1744898750110.png" /></span></P><P>Setting up an <STRONG>SAP BTP Trial account</STRONG> and connecting it to <STRONG>ABAP Development Tools</STRONG> is the first step toward learning modern SAP development.</P><P>With this trial environment, you can:</P><UL><LI><P>Practice ABAP Cloud &amp; RAP</P></LI><LI><P>Explore SAP BTP services</P></LI><LI><P>Build and test applications safely in a non-production system</P></LI></UL><P>Setting up an SAP BTP Trial account and connecting it to ABAP Development Tools in Eclipse is a very straightforward, yet powerful, first step into the world of modern SAP development. Within a few steps, you have hands-on access to an ABAP Cloud environment where you can learn, experiment, and build with no cost and risk.</P><P>This trial setup lets you understand the latest development paradigm of SAP, practice ABAP Cloud and RAP concepts, and experience the broader capabilities of SAP Business Technology Platform on an actual system. Whether you are a novice or experienced ABAP developer moving to cloud-based development, SAP Business Technology Platform Trial is your ideal playground where you can upskill yourself for all future SAP projects.</P><P>In short, investing in setting up and using the SAP BTP Trial today lays a great foundation for becoming proficient with next-generation SAP development tomorrow.</P><P>&nbsp;</P> 2025-12-12T08:59:14.528000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/how-to-use-sap-extensibility-wizard-in-sap-s-4hana-clean-core/ba-p/14290385 How to Use SAP Extensibility Wizard in SAP S/4HANA Clean Core 2025-12-23T07:13:48.565000+01:00 ahmedyehia9 https://community.sap.com/t5/user/viewprofilepage/user-id/803721 <P><!-- StartFragment --></P><P><STRONG>A Comprehensive Guide to Extending SAP S/4HANA with the SAP Extensibility Wizard — Without Compromising Your Clean Core</STRONG></P><P><U><STRONG>Introduction</STRONG></U></P><P>Extensibility is a critical aspect of SAP S/4HANA, enabling organizations to tailor the system to their unique business needs while maintaining stability and upgrade readiness. In this guide, we will explore the <STRONG>SAP Extensibility Wizard</STRONG>, a powerful tool designed to help developers extend SAP S/4HANA in a clean and controlled way.</P><P><STRONG><U>What Is the SAP Extensibility Wizard?</U></STRONG></P><P>The <STRONG>SAP Extensibility Wizard</STRONG> is a guided tool provided by SAP that simplifies the process of creating extensions. It ensures that developers can add custom functionality without modifying the core system, thereby preserving the <EM>clean core</EM> principle. This approach guarantees that upgrades remain smooth and that the&nbsp;system stays resilient over time.</P><P><U><STRONG>Availability: Public Cloud vs. Private Cloud</STRONG></U></P><P>A common question arises: <EM>Is the SAP Extensibility Wizard available only in the Public Cloud, or also in the Private Cloud?</EM></P><UL><LI><STRONG>Public Cloud (SAP S/4HANA Cloud – Public Edition):</STRONG><BR />The wizard is primarily available here. It supports clean-core extensibility and helps organizations build safe, upgrade‑friendly extensions.</LI><LI><STRONG>Private Cloud / On‑Premise:</STRONG><BR />Extensibility is possible through other approaches such as <STRONG>in‑app extensibility</STRONG>, <STRONG>ABAP Cloud</STRONG>, and <STRONG>side‑by‑side extensions on SAP BTP</STRONG>. However, the wizard itself is not provided in the same way as in the Public Cloud.</LI></UL><P><!-- StartFragment --></P><P><STRONG>In summary:</STRONG></P><UL><LI>Public Cloud → Wizard available.</LI><LI>Private Cloud / On‑Premise → Extensibility options exist, but without the wizard.</LI></UL><P><U><STRONG>Focus of This Blog</STRONG></U></P><P>This blog will focus on the <STRONG>SAP Extensibility Wizard for SAP S/4HANA Cloud – Public Edition</STRONG>.</P><P><!-- EndFragment --><!-- StartFragment --></P><P>How to Use the Extensibility Wizard</P><P>With the SAP S/4HANA Cloud Public Edition extensibility wizard, developers can:</P><UL><LI><STRONG>Create on‑stack extensions</STRONG> such as custom fields and custom logic.</LI><LI><STRONG>Build side‑by‑side extensions</STRONG> like custom processes using <STRONG>SAP Build Process Automation</STRONG>.</LI></UL><P>This guided approach ensures that extensions are implemented efficiently, securely, and in alignment with SAP’s clean‑core strategy.</P><P><U><STRONG>Conclusion</STRONG></U></P><P>The <STRONG>SAP Extensibility Wizard</STRONG> is a key enabler for organizations running SAP S/4HANA Cloud Public Edition. By leveraging this tool, businesses can extend their systems with confidence, ensuring that customizations remain upgrade‑safe and future‑proof.</P><P>&nbsp;</P><P><!-- EndFragment --></P><P><!-- EndFragment --></P><P><!-- EndFragment --></P><P><STRONG><SPAN><U>Detailed Steps:</U></SPAN></STRONG></P><P><STRONG><SPAN><U>Use Case :</U></SPAN><SPAN>&nbsp;We will create a sales order approval process .</SPAN></STRONG></P><P class="lia-indent-padding-left-30px" style="padding-left : 30px;"><STRONG><SPAN><U>1. Navigate to SAP S4/HANA Fiori Launchpad.</U></SPAN></STRONG></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><STRONG>1.1 <SPAN><U>Select Business Application Manage Sales Orders.&nbsp;</U></SPAN></STRONG></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_0-1765834104246.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352339i91F62F84C5AB9BDE/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_0-1765834104246.png" alt="ahmedyehia9_0-1765834104246.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.2&nbsp;&nbsp;<SPAN class="">Navigate to Create Extension</SPAN></STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_1-1765835538668.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352344i459BD0772768EF2C/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_1-1765835538668.png" alt="ahmedyehia9_1-1765835538668.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_2-1765835643824.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352345iBD182EF1112D4E2B/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_2-1765835643824.png" alt="ahmedyehia9_2-1765835643824.png" /></span></P><P>&nbsp;</P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.3 In this case , we will select custom process.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_3-1765835770046.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352346i9861EC014341E37E/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_3-1765835770046.png" alt="ahmedyehia9_3-1765835770046.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;">The process can start based on various triggers&nbsp;</P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.4 Select Business Event from SAP S4/HANA, that Triggers the process</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_3-1765964349459.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352986i5DF86AB2863FD894/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_3-1765964349459.png" alt="ahmedyehia9_3-1765964349459.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.5 Select Event Object</STRONG></SPAN></P><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_0-1766054851277.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/353528i8F3DABA18FBD5A90/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_0-1766054851277.png" alt="ahmedyehia9_0-1766054851277.png" /></span></DIV><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.6 Select the SalesOrder create event.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_6-1765836099992.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352349i6FBE6C976C5237A6/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_6-1765836099992.png" alt="ahmedyehia9_6-1765836099992.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.7 Click Preview to see all the options you selected on previous screens, and make any necessary corrections.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_7-1765836274304.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352350i7E8D51F75B7D8373/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_7-1765836274304.png" alt="ahmedyehia9_7-1765836274304.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.8 Click Create , to create the process in SAP Build.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_8-1765836432554.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352351i115237BDD9C3F187/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_8-1765836432554.png" alt="ahmedyehia9_8-1765836432554.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.9 The extension is now available and can also be opened in SAP Build.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_9-1765836549398.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352352i31CCC05F9800CFB1/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_9-1765836549398.png" alt="ahmedyehia9_9-1765836549398.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.10 When you select Open Extension, the system launches another tab that opens the process.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_10-1765836669849.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352353i1BB38AA5DD08A534/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_10-1765836669849.png" alt="ahmedyehia9_10-1765836669849.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.11 The Process Automation project overview page is now displayed. Select SalesOrder Approval.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_11-1765836836220.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352355i47B44A41CDB28FE0/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_11-1765836836220.png" alt="ahmedyehia9_11-1765836836220.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.12 Extension is now openEd in SAP Build , Start design of the process.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>The Business context is carried over from SAP S4/HANA to SAP Build .</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_0-1765874183680.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352505iF1FDFBE39F95630B/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_0-1765874183680.png" alt="ahmedyehia9_0-1765874183680.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.13 You can add an action, form , or approval . To get further details on the sales order, you need to call an action .</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_1-1765874475245.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352517iCBB3B0B64C54F079/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_1-1765874475245.png" alt="ahmedyehia9_1-1765874475245.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.14 In this use case , we will call sales order read API , to fetch the sales order details.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_2-1765874611731.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352518i440DB912AD85229E/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_2-1765874611731.png" alt="ahmedyehia9_2-1765874611731.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.15 Browse the library to search for&nbsp; the relevant APIs .</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_3-1765874731152.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352519i5596679844740296/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_3-1765874731152.png" alt="ahmedyehia9_3-1765874731152.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.16 Select read sales order API to get details of the sales order, The business context and system ID were automatically pulled in from SAP S4/HANA .</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_4-1765874972943.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352522i36CE20BEFFDBCE90/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_4-1765874972943.png" alt="ahmedyehia9_4-1765874972943.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.17 The action to read the sales order has now been added . Now users can design the process according to their needs. The user now wants to initiate a workflow that sends an email to the approver for sales order approval .</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_5-1765875108309.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352524iC01561336C140883/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_5-1765875108309.png" alt="ahmedyehia9_5-1765875108309.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.18 The email will include the sales order details , allowing approver to review and approve it . we're utilizing AI to generate the process , Enter the prompt to add an approval step and send the sales order details to the approver via email.</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_6-1765875296166.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352526i795E93D5EFBDF600/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_6-1765875296166.png" alt="ahmedyehia9_6-1765875296166.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><SPAN><STRONG>1.19 AI has now added the process step to read the sales order and email, The sales order details to the approver .</STRONG></SPAN></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ahmedyehia9_0-1765896023701.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/352780iED7CB3058677CB55/image-size/medium?v=v2&amp;px=400" role="button" title="ahmedyehia9_0-1765896023701.png" alt="ahmedyehia9_0-1765896023701.png" /></span></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;">&nbsp;</P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><!-- StartFragment --></P><P><U><STRONG>Conclusion</STRONG></U></P><P>The <STRONG>SAP Extensibility Wizard</STRONG> empowers organizations running SAP S/4HANA Cloud Public Edition to extend their systems safely and efficiently, without compromising the clean core. By leveraging guided tools for custom fields, logic, and side‑by‑side processes, businesses can innovate while staying upgrade‑ready.</P><P>Extensibility in SAP is not just about adding features—it’s about doing so in a way that keeps your system future‑proof. With the wizard, you can confidently build the extensions your business needs today, while ensuring smooth upgrades tomorrow.</P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><!-- EndFragment --></P><P class="lia-indent-padding-left-60px" style="padding-left : 60px;"><!-- StartFragment --></P><P><!-- EndFragment --></P><P>&nbsp;</P> 2025-12-23T07:13:48.565000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/custom-entity-with-actions/ba-p/14298105 Custom Entity With Actions 2026-01-11T23:45:05.274000+01:00 kalmesh https://community.sap.com/t5/user/viewprofilepage/user-id/1490139 <P><STRONG><SPAN>What is a Custom Entity in RAP?</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>In the&nbsp;</SPAN><STRONG><SPAN>ABAP RESTful Application Programming Model (RAP)</SPAN></STRONG><SPAN>, a Custom Entity is a CDS entity that does not map to a database table. Instead, it&nbsp;represents&nbsp;virtual data&nbsp;provided by custom ABAP logic. It is used when:</SPAN><SPAN>&nbsp;</SPAN></P><UL><LI><SPAN>You need to expose calculated or external data.</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>You want to integrate non-database sources (e.g., APIs, external systems).</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>You&nbsp;require&nbsp;custom operations beyond standard CRUD.</SPAN><SPAN>&nbsp;</SPAN></LI></UL><P><SPAN>Adding an Action to a Custom Entity allows you to trigger specific business operations directly from the UI.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Now we will look at one practical example for</SPAN><STRONG><SPAN>&nbsp;Custom Entity with an Action</SPAN></STRONG><SPAN>&nbsp;in RAP, where the action will be performed based on&nbsp;the user&nbsp;click on&nbsp;the button&nbsp;called&nbsp;</SPAN><STRONG><SPAN>CustomAction</SPAN></STRONG><SPAN>&nbsp;, when user clicks on&nbsp;it&nbsp;the icon will&nbsp;be&nbsp;changed.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN><SPAN class=""><SPAN class="">First, we will begin by creating a database table with the fields shown in the screenshot below.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="kalmesh_0-1766832080906.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356220iC0945965AA796F9D/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_0-1766832080906.png" alt="kalmesh_0-1766832080906.png" /></span></P><P><SPAN class=""><SPAN class="">Next, we will create a Custom Entity and define its implementation class, as the Custom Entity will be realized through the logic implemented in that class<SPAN>&nbsp;<STRONG>"</STRONG></SPAN></SPAN></SPAN><STRONG><SPAN class=""><SPAN class="">ZGA_CL_QRY_PRVD_C_ACT"</SPAN></SPAN><SPAN class=""><SPAN class="">.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="kalmesh_1-1766832144208.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356221iF68A33E3914A42CE/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_1-1766832144208.png" alt="kalmesh_1-1766832144208.png" /></span></P><P><SPAN class=""><SPAN class="">Now, we will implement the logic in the class and use the mandatory interface<SPAN>&nbsp;</SPAN></SPAN></SPAN><STRONG><SPAN class=""><SPAN class="">IF_RAP_QUERY_PROVIDER</SPAN></SPAN></STRONG><SPAN class=""><SPAN class=""><SPAN>&nbsp;</SPAN>to handle data retrieval for the Custom Entity.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="kalmesh_2-1766832199325.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356222i55919012BA7B99BD/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_2-1766832199325.png" alt="kalmesh_2-1766832199325.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="kalmesh_3-1766832228505.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356223iC293655E1C46FFBC/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_3-1766832228505.png" alt="kalmesh_3-1766832228505.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="kalmesh_4-1766832260644.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356224iDA33478AA477F830/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_4-1766832260644.png" alt="kalmesh_4-1766832260644.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN class=""><SPAN class="">To adjust the data, we have implemented another class named<SPAN>&nbsp;</SPAN></SPAN></SPAN><SPAN class=""><STRONG><SPAN class="">ZGA_CL_BS_DEMO_ADJUST_DATA</SPAN></STRONG><SPAN class="">.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="kalmesh_5-1766832307318.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356225iCFBAEE44B32120F2/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_5-1766832307318.png" alt="kalmesh_5-1766832307318.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="kalmesh_6-1766832329748.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356226i00CB29C2A5AC119E/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_6-1766832329748.png" alt="kalmesh_6-1766832329748.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="kalmesh_7-1766832350606.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356227i388347BF2A873C50/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_7-1766832350606.png" alt="kalmesh_7-1766832350606.png" /></span></P><P><SPAN class=""><SPAN class="">Our next task is to create a Behavior Definition for the Custom Entity<STRONG>&nbsp;</STRONG></SPAN></SPAN><STRONG><SPAN class=""><SPAN class="">ZGA_I_CUST_ACT_DEMO</SPAN></SPAN></STRONG><SPAN class=""><SPAN class=""><SPAN>&nbsp;</SPAN>to enable actions and logic implementation.</SPAN></SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="kalmesh_8-1766832393668.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356228iAECD7C2410EF7417/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_8-1766832393668.png" alt="kalmesh_8-1766832393668.png" /></span></P><P><SPAN class=""><SPAN class="">Next, we dive into implementing the Behavior Definition logic in the class<SPAN>&nbsp;</SPAN></SPAN></SPAN><STRONG><SPAN class=""><SPAN class="">ZBP_GA_I_CUST_ACT_DEMO</SPAN></SPAN><SPAN class=""><SPAN class="">.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="kalmesh_9-1766832426916.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356229iF70A9CC482E83532/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_9-1766832426916.png" alt="kalmesh_9-1766832426916.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_10-1766832456178.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356230i2885317CFCD98496/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_10-1766832456178.png" alt="kalmesh_10-1766832456178.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_11-1766832498326.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356231i9B1588FFEF011058/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_11-1766832498326.png" alt="kalmesh_11-1766832498326.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_12-1766832520415.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356232iDD4420BF98C30195/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_12-1766832520415.png" alt="kalmesh_12-1766832520415.png" /></span></P><P><SPAN class=""><SPAN class="">The class shown below serves as the buffer class, which we have<SPAN>&nbsp;</SPAN></SPAN><SPAN class="">utilized</SPAN><SPAN class=""><SPAN>&nbsp;</SPAN>in our Behavior Implementation class.</SPAN></SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_13-1766832562156.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356233iE4E056DD4B8B7064/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_13-1766832562156.png" alt="kalmesh_13-1766832562156.png" /></span></P><P><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class="">Our next task is to create the Service Definition and Service Binding, enabling the UI to consume the Custom Entity and its actions.</SPAN></SPAN></SPAN></SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_14-1766832825025.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356234i2AB488EE42C37280/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_14-1766832825025.png" alt="kalmesh_14-1766832825025.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_15-1766832846396.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356235i62F457A5489BD6D4/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_15-1766832846396.png" alt="kalmesh_15-1766832846396.png" /></span></P><P>&nbsp;</P><P><STRONG><SPAN class=""><SPAN class="">Output:</SPAN></SPAN></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_16-1766832881804.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356236i57FFFB99665254AC/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_16-1766832881804.png" alt="kalmesh_16-1766832881804.png" /></span></P><P><SPAN class=""><SPAN class="">Once an instance is selected, clicking<SPAN>&nbsp;</SPAN></SPAN></SPAN><STRONG><SPAN class=""><SPAN class="">CustomAction</SPAN></SPAN></STRONG><SPAN class=""><SPAN class=""><SPAN>&nbsp;</SPAN>will dynamically update the icon, as displayed in the screenshot.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_17-1766832948228.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356237iD501E9D2A9E5D609/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_17-1766832948228.png" alt="kalmesh_17-1766832948228.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_18-1766832988928.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356238i4234920EFFA49F20/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_18-1766832988928.png" alt="kalmesh_18-1766832988928.png" /></span></P><P><SPAN class=""><SPAN class="">The<SPAN>&nbsp;</SPAN></SPAN></SPAN><STRONG><SPAN class=""><SPAN class="">Reset</SPAN></SPAN></STRONG><SPAN class=""><SPAN class=""><SPAN>&nbsp;</SPAN>button&nbsp;is used to restore all icons to their original state.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="kalmesh_19-1766833046155.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/356239i562018DBC6C0CD67/image-size/large?v=v2&amp;px=999" role="button" title="kalmesh_19-1766833046155.png" alt="kalmesh_19-1766833046155.png" /></span></P><P><STRONG><SPAN>Conclusion</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>Custom Entities with Actions in SAP RAP&nbsp;provide&nbsp;a powerful way to implement dynamic, user-driven functionality without relying on database persistence. In this example, we&nbsp;demonstrated&nbsp;how to create a Custom Entity and enhance it with two actions.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>By&nbsp;leveraging&nbsp;actions, you can enrich your applications with flexible business logic, improve user engagement, and&nbsp;maintain&nbsp;a clean separation between UI and backend logic. This approach is ideal for scenarios where you need virtual data handling combined with interactive operations.</SPAN><SPAN>&nbsp;</SPAN></P> 2026-01-11T23:45:05.274000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/research-unmanaged-transactional-buffer-for-restful-application-programming/ba-p/14289323 Research: Unmanaged Transactional Buffer For RESTful Application Programming Model 2026-01-19T12:23:34.134000+01:00 PrusakouIlya https://community.sap.com/t5/user/viewprofilepage/user-id/1769851 <P class="lia-align-center" style="text-align: center;"><FONT size="5"><FONT face="georgia,palatino"><STRONG>RESEARCH ON UNMANAGED IMPLEMENTATION OF TRANSACTIONAL BUFFER FOR RESTFUL APPLICATION PROGRAMMING MODEL</STRONG></FONT></FONT></P><P class="lia-align-center" style="text-align: center;"><FONT size="2"><EM><FONT face="georgia,palatino"><STRONG>Ilya Prusakou<BR />ABAP Developer &amp; Researcher</STRONG></FONT></EM></FONT></P><P class="lia-align-center" style="text-align: center;">&nbsp;</P><P class="lia-align-center" style="text-align: center;"><U><FONT face="georgia,palatino" size="5"><STRONG>Abstract</STRONG>.</FONT></U></P><P><FONT size="3">Implementing unmanaged scenarios in the ABAP RESTful Application Programming Model (RAP) remains a significant hurdle for developers due to the opinionated nature of the framework and a lack of production-level examples.<BR />The research addresses the challenge by providing comprehensive blueprint for the unmanaged transactional buffer. This article serves as a practical guide for mastering the internal state management of RAP business objects.</FONT></P><P><FONT size="3"><STRONG>KEYWORDS:</STRONG>&nbsp;<EM>Unmanaged Implementation, Transactional Buffer, Buffer Tables, Complex Data Source, Buffer Preparation, Buffer Flags, Draft Buffer, Buffer Access, Transactional Phase, Save Phase, Late Numbering.</EM></FONT></P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="5"><U><STRONG>Examples</STRONG>.</U></FONT></P><P><FONT face="arial,helvetica,sans-serif" size="3">You can find example of buffer implementation on my github:&nbsp;<A href="https://github.com/IlyaPrusakou/rap-unmanaged-buffer-example.git" target="_blank" rel="noopener nofollow noreferrer">https://github.com/IlyaPrusakou/rap-unmanaged-buffer-example.git</A></FONT></P><P><FONT face="arial,helvetica,sans-serif" size="3">The specific path is <STRONG>src/zpru_transactional_buffer/zpru_cl_example_buffer.clas.abap<BR /></STRONG>You can also review the buffer class code at the bottom of this article. In this post, I will use term "<STRONG>blueprint</STRONG>" referring to the full code of the example implementation.</FONT></P><P><FONT face="arial,helvetica,sans-serif" size="3">Additionally, you can visit my another github rep:&nbsp;<A href="https://github.com/IlyaPrusakou/abap-rap-example.git" target="_blank" rel="noopener nofollow noreferrer">https://github.com/IlyaPrusakou/abap-rap-example.git</A></FONT></P><P><FONT face="arial,helvetica,sans-serif" size="3">My unmanaged imlementation class on which I have provided my research is under the path:&nbsp;<STRONG>src/zpru_um_po/zpru_um_po_implmtns/zbp_pru_u_purcorderhdr_tp.clas.locals_imp.abap</STRONG></FONT></P><P><FONT face="arial,helvetica,sans-serif" size="3">There, you can look onto the local class&nbsp;<STRONG>LCL_BUFFER</STRONG>.</FONT><BR /><FONT face="arial,helvetica,sans-serif" size="3">To check out how to use the buffer for standard operations, you can visit the local handler class&nbsp;<STRONG>LHC_ORDERTP,</STRONG> specifically methods:&nbsp;</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ORDERTP~CREATE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ORDERTP~READ</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ORDERTP~UPDATE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ORDERTP~DELETE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ORDERTP~RBA_ITEMS_TP</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ORDERTP~CBA_ITEMS_TP</FONT></LI></UL><P><FONT face="arial,helvetica,sans-serif" size="3">For investigation of the child node, you can open the local handler&nbsp;<STRONG>LHC_ITEMTP</STRONG>, specifically methods:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ITEMTP~READ</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ITEMTP~UPDATE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ITEMTP~DELETE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif" size="3">LHC_ITEMTP~RBA_HEADER_TP</FONT></LI></UL><P><FONT face="arial,helvetica,sans-serif" size="3">It is recomended to have a glance into the local saver class&nbsp;<STRONG>LSC_ZPRU_U_PURCORDERHDR_TP</STRONG> to understand how a trigger calculation works and what role method FINALIZE, CHECK_BEFORE_SAVE and SAVE play.</FONT></P><P><FONT face="arial,helvetica,sans-serif" size="3">I also recommend visiting the packages <STRONG>SABAP_DEMOS_RAP</STRONG> and <STRONG>SABAP_DEMOS_RAP_CLOUD</STRONG> to check out various RAP examples, especially BDEF&nbsp;&nbsp;<SPAN><STRONG>DEMO_RAP_UNMANAGED_DRAFT_ROOT</STRONG> and its&nbsp; associated class.</SPAN></FONT></P><P><FONT face="arial,helvetica,sans-serif" size="3">For the <STRONG>blueprint implementation</STRONG> I have used a RAP business object with an <STRONG>unmanaged implementation type</STRONG> and with four nested levels.</FONT><BR /><FONT face="arial,helvetica,sans-serif" size="3">Moreover, I used a late numbering because it requires the maximum implementation effort. I also defined keys using simple character types rather than GUID fields.</FONT><BR />&nbsp;&nbsp;</P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="5"><U><STRONG>Buffer class</STRONG>.</U></FONT></P><P><FONT face="arial,helvetica,sans-serif">From an implementation perspective a <STRONG>transactinal buffer is ABAP class</STRONG>, usually <STRONG>local class</STRONG> placed in local implementation include of ABAP behavior implementation global class (ABP class). It contains <STRONG>entity buffer tables.<BR /></STRONG>Buffer class can be an ABAP global class as well. However, if you choose this way of implementation you must be aware that global class is considered as external to the ABP class and you will not be able to access <STRONG>internal derived types</STRONG>.</FONT></P><P>&nbsp;</P><TABLE border="1" width="100%"><TBODY><TR><TD height="30px"><FONT face="arial,helvetica,sans-serif"><STRONG>Accessible types</STRONG></FONT></TD><TD height="30px"><FONT face="arial,helvetica,sans-serif"><STRONG>Internal types</STRONG></FONT></TD></TR><TR><TD width="50%" height="30px"><FONT face="arial,helvetica,sans-serif">keys type <STRONG>table for read import</STRONG> bdef\\entity</FONT></TD><TD width="50%" height="30px"><FONT face="arial,helvetica,sans-serif">keys type <STRONG>table for validation</STRONG> bdef\\entity~validation</FONT></TD></TR><TR><TD width="50%" height="57px"><FONT face="arial,helvetica,sans-serif">entitie type <STRONG>table for create</STRONG> bdef\\entity</FONT></TD><TD width="50%" height="57px"><FONT face="arial,helvetica,sans-serif">keys type <STRONG>table for determination</STRONG> bdef\\entity~determination</FONT></TD></TR><TR><TD width="50%" height="30px"><FONT face="arial,helvetica,sans-serif">keys type <STRONG>table for action import</STRONG> bdef\\entity~action</FONT></TD><TD width="50%" height="30px"><FONT face="arial,helvetica,sans-serif">event type <STRONG>table for event</STRONG> bdef~event</FONT></TD></TR><TR><TD width="50%" height="30px"><FONT face="arial,helvetica,sans-serif">etc.</FONT></TD><TD width="50%" height="30px"><FONT face="arial,helvetica,sans-serif">etc.</FONT></TD></TR></TBODY></TABLE><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Entity buffer tables</STRONG>.</U></FONT></P><P><FONT face="arial,helvetica,sans-serif">Entity buffer tables are <STRONG>internal tables</STRONG> defined as <STRONG>static attributes</STRONG> in a buffer class. Their rows contain <STRONG>entity fields</STRONG> from the transactional CDS, <STRONG>flags</STRONG> (changed, deleted) and other <STRONG>components</STRONG>(CID, PID etc.)</FONT><BR /><FONT face="arial,helvetica,sans-serif">In the snippet of code below, you can observe entity buffer tables on rows 42 - 45. Besides the tables themselves, there are <STRONG>types for entity keys</STRONG> and <STRONG>types for the buffer rows</STRONG> as well.</FONT></P><pre class="lia-code-sample language-abap"><code>CLASS zpru_cl_example_buffer DEFINITION PUBLIC FINAL CREATE PUBLIC. " types for entity keys TYPES: BEGIN OF ts_first_node_db_keys, firstkey TYPE zr_pru_1st_node-firstkey, END OF ts_first_node_db_keys. TYPES: BEGIN OF ts_second_node_db_keys, firstkey TYPE zr_pru_2nd_node-firstkey, secondkey TYPE zr_pru_2nd_node-secondkey, END OF ts_second_node_db_keys. ***** ***** " types for buffer row TYPES: BEGIN OF ts_first_node, instance TYPE zr_pru_1st_node, cid TYPE abp_behv_cid, pid TYPE abp_behv_pid, final_key TYPE ts_first_node_db_keys, changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_first_node. TYPES: BEGIN OF ts_second_node, instance TYPE zr_pru_2nd_node, cid TYPE abp_behv_cid, pid TYPE abp_behv_pid, pidparent TYPE abp_behv_pid, final_key TYPE ts_second_node_db_keys, changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_second_node. ***** ***** " entity buffer tables TYPES tt_first_node TYPE TABLE OF ts_first_node WITH EMPTY KEY. TYPES tt_second_node TYPE TABLE OF ts_second_node WITH EMPTY KEY. TYPES tt_third_node TYPE TABLE OF ts_third_node WITH EMPTY KEY. TYPES tt_fourth_node TYPE TABLE OF ts_fourth_node WITH EMPTY KEY. CLASS-DATA st_first_node TYPE tt_first_node. CLASS-DATA st_second_node TYPE tt_second_node. CLASS-DATA st_third_node TYPE tt_third_node. CLASS-DATA st_fourth_node TYPE tt_fourth_node. ***** ***** ENDCLASS.</code></pre><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Buffer preparation</STRONG>.</U></FONT></P><P><FONT face="arial,helvetica,sans-serif">The <STRONG>buffer preparation</STRONG> is the process of <STRONG>loading entities</STRONG> from a complex data source (in my case, it is just a transactional CDS) into <STRONG>entity buffer tables</STRONG>, usually executed via <STRONG>static methods</STRONG> (e.g. PREP_ENTITY_NAME) in the buffer class.</FONT><BR /><FONT face="arial,helvetica,sans-serif">Each <STRONG>standard RAP operations</STRONG> will start with the <STRONG>buffer preparation methods</STRONG>. You may know these operations by names such as preloading, fetching, selecting data into the buffer, or even prepopulating the buffer.</FONT><BR /><FONT face="arial,helvetica,sans-serif">Moreover, I want to draw attention to type definitions for the input parameters of the preparation methods - especially to the flag FULL_KEY. The flag belongs to child entities and is used to distinguish between accessing them <STRONG>via association</STRONG> or <STRONG>direct access</STRONG>.</FONT></P><pre class="lia-code-sample language-abap"><code>CLASS zpru_cl_example_buffer DEFINITION PUBLIC FINAL CREATE PUBLIC. ***** ***** "structure types for input parameters for buffer preparation methods TYPES: BEGIN OF ts_first_node_keys. INCLUDE TYPE ts_first_node_db_keys. TYPES: END OF ts_first_node_keys. TYPES: BEGIN OF ts_second_node_keys. INCLUDE TYPE ts_second_node_db_keys. TYPES: full_key TYPE abap_bool, END OF ts_second_node_keys. ***** ***** "table types for input parameters for buffer preparation methods TYPES tt_first_node_keys TYPE TABLE OF ts_first_node_keys WITH EMPTY KEY. TYPES tt_second_node_keys TYPE TABLE OF ts_second_node_keys WITH EMPTY KEY. ***** ***** " buffer preparation methods CLASS-METHODS prep_first_node_buffer IMPORTING !keys TYPE tt_first_node_keys. CLASS-METHODS prep_second_node_buffer IMPORTING !keys TYPE tt_second_node_keys. CLASS-METHODS prep_third_node_buffer IMPORTING !keys TYPE tt_third_node_keys. CLASS-METHODS prep_fourth_node_buffer IMPORTING !keys TYPE tt_fourth_node_keys. ENDCLASS.</code></pre><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Root preparation</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">Let's check code inside the preparation method for root entity.</FONT>&nbsp;</P><pre class="lia-code-sample language-abap"><code> METHOD prep_first_node_buffer. DATA lt_keys_2_read LIKE keys. DATA lt_entity_result TYPE STANDARD TABLE OF zr_pru_1st_node WITH EMPTY KEY. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;ls_key&gt;). IF line_exists( zpru_cl_example_buffer=&gt;st_first_node[ instance-firstkey = &lt;ls_key&gt;-firstkey ] ). CONTINUE. ELSE. APPEND INITIAL LINE TO lt_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_key_2_read&gt;). &lt;ls_key_2_read&gt;-firstkey = &lt;ls_key&gt;-firstkey. ENDIF. ENDLOOP. IF lt_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_1st_node FOR ALL ENTRIES IN lt_keys_2_read WHERE firstkey = lt_keys_2_read-firstkey INTO TABLE lt_entity_result. IF sy-subrc = 0. LOOP AT lt_entity_result ASSIGNING FIELD-SYMBOL(&lt;ls_result&gt;). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_first_node ASSIGNING FIELD-SYMBOL(&lt;ls_buffer&gt;). &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDLOOP. ENDIF. ENDIF. ENDMETHOD.</code></pre><P><FONT face="arial,helvetica,sans-serif"><STRONG>Root preparation logic</STRONG> is the following:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif">check if the entry exists in the buffer using the full key</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">if yes:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">do nothing</FONT></LI></UL></LI><LI><FONT face="arial,helvetica,sans-serif">if no:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">collect keys to select data from the data source</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">select data using the full key</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">insert entry into the buffer</FONT></LI></UL></LI></UL></LI></UL><P><FONT face="arial,helvetica,sans-serif"><STRONG>Checking existence</STRONG> and <STRONG>reading data</STRONG> based on<STRONG> buffer keys</STRONG>, which can be <STRONG>full</STRONG> or<STRONG> partial</STRONG> and depending on whether we are reading a <STRONG>root </STRONG>or<STRONG> child entity</STRONG>, and whether the access is <STRONG>direct</STRONG> or <STRONG>via association</STRONG>. In the case of a <STRONG>root entity</STRONG>, it is always a <STRONG>full key</STRONG>. Even when we try to access the <STRONG>parent node</STRONG> (especially the root node) from a child entity, we use "<STRONG>to-parent</STRONG>" <STRONG>association</STRONG> and provide the <STRONG>full key</STRONG>. I will explain buffer keys in separate chapter.</FONT></P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Child preparation</STRONG></U></FONT></P><P>Let's check code inside the preparation method for child entity. This is where the flag FULL_KEY comes into play.</P><pre class="lia-code-sample language-abap"><code> METHOD prep_second_node_buffer. DATA lt_full_keys_2_read LIKE keys. DATA lt_part_keys_2_read LIKE keys. DATA lt_full_entity_result TYPE STANDARD TABLE OF zr_pru_2nd_node WITH EMPTY KEY. DATA lt_part_entity_result TYPE STANDARD TABLE OF zr_pru_2nd_node WITH EMPTY KEY. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;ls_key_child&gt;). IF &lt;ls_key_child&gt;-full_key = abap_true. IF line_exists( zpru_cl_example_buffer=&gt;st_second_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey ] ). CONTINUE. ELSE. APPEND INITIAL LINE TO lt_full_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_full_key_2_read&gt;). &lt;ls_full_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. &lt;ls_full_key_2_read&gt;-secondkey = &lt;ls_key_child&gt;-secondkey. ENDIF. ELSE. IF line_exists( zpru_cl_example_buffer=&gt;st_first_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey ] ) AND VALUE #( zpru_cl_example_buffer=&gt;st_first_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey ]-deleted OPTIONAL ) IS NOT INITIAL. CONTINUE. ELSE. APPEND INITIAL LINE TO lt_part_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_part_key_2_read&gt;). &lt;ls_part_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. ENDIF. ENDIF. ENDLOOP. IF lt_full_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_2nd_node FOR ALL ENTRIES IN _full_keys_2_read WHERE firstkey = lt_full_keys_2_read-firstkey AND secondkey = lt_full_keys_2_read-secondkey INTO TABLE lt_full_entity_result. IF sy-subrc = 0. LOOP AT lt_full_entity_result ASSIGNING FIELD-SYMBOL(&lt;ls_result&gt;). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_second_node ASSIGNING FIELD-SYMBOL(&lt;ls_buffer&gt;). &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDLOOP. ENDIF. ENDIF. IF lt_part_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_2nd_node FOR ALL ENTRIES IN lt_part_keys_2_read WHERE firstkey = lt_part_keys_2_read-firstkey INTO TABLE lt_part_entity_result. IF sy-subrc = 0. LOOP AT lt_part_entity_result ASSIGNING &lt;ls_result&gt;. IF NOT line_exists( zpru_cl_example_buffer=&gt;st_second_node[ instance-firstkey = &lt;ls_result&gt;-firstkey instance-secondkey = &lt;ls_result&gt;-secondkey ] ). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_second_node ASSIGNING &lt;ls_buffer&gt;. &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDIF. ENDLOOP. ENDIF. ENDIF. ENDMETHOD.</code></pre><P><FONT face="arial,helvetica,sans-serif">Let's explore logic.</FONT></P><UL class="lia-list-style-type-circle"><LI><FONT face="arial,helvetica,sans-serif">check if the key is a full key:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">if it is a full key:&nbsp;</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">check if the entry exists in the buffer using the full key:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">if yes:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">do nothing&nbsp;</FONT></LI></UL></LI><LI><FONT face="arial,helvetica,sans-serif">if no:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">collect the key to select data from the data source</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">select data using the full key</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">insert the child entry into the buffer</FONT></LI></UL></LI></UL></LI></UL></LI><LI><FONT face="arial,helvetica,sans-serif">if it is a partial key:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">check if the parent node is marked for deletion in the buffer&nbsp;</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">if yes:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">do nothing</FONT></LI></UL></LI><LI><FONT face="arial,helvetica,sans-serif">if no:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">collect the key to select data from the data source</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">select one or multiple child entities using the partial key</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">loop through the selection result:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">check if each processing child entity already exists in the buffer</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">if it does not exist: add it into the buffer table</FONT></LI></UL></LI></UL></LI></UL></LI></UL></LI></UL></LI></UL></LI></UL><P><FONT face="arial,helvetica,sans-serif">You may ask why we check if the <STRONG>parent node</STRONG>, marked for <STRONG>deletion</STRONG>, exists in the buffer in the <STRONG>partial key logic</STRONG>. The answer is that when we mark for deletion parent node, we must <STRONG>mark for deletion all its children (cascading deletion).</STRONG></FONT><BR /><FONT face="arial,helvetica,sans-serif">This is the only scenario where we can be certain that <STRONG>all children are already present</STRONG> in the buffer. In other cases, we can't guarantee that all children are buffered; for example only four out of five children might currently be loaded.</FONT></P><P><FONT face="arial,helvetica,sans-serif">You may also ask why we check if a child entry exists before inserting it into the buffer table in the partial key logic. Let me give you an example. We have one parent node and four children:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif">parent1</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">child1</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">child2</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">child3</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">child4</FONT></LI></UL></LI></UL><P><FONT face="arial,helvetica,sans-serif">Firstly, you do operation "read child1"; as a result you have child1 inside the buffer table. Then you perform a "<STRONG>read by associations</STRONG>" for the children of parent1.</FONT><BR /><FONT face="arial,helvetica,sans-serif">During <STRONG>child preparation method</STRONG> you will have only the parent key (the partial key logic) and you will select all children of parent1 (child1, child2, child3 and child4). So the next step is to insert all of these children into <STRONG>the buffer table</STRONG>, but child1 is already presented. To <STRONG>avoid duplicates</STRONG> in the buffer table, we <STRONG>check for the existence</STRONG> of the child entity before inserting.&nbsp;</FONT></P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Full Buffer key vs Partial Buffer key.</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">During <STRONG>checking existence in the buffer</STRONG> or <STRONG>reading data from data source</STRONG> we use either the full key or the partial key of the entity:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif"><SPAN><STRONG>The partial key logic</STRONG>: used when we access the entity <STRONG>via composition</STRONG>. The partial key logic take place when we <STRONG>move from parent to child</STRONG>.</SPAN></FONT></LI><LI><FONT face="arial,helvetica,sans-serif"><SPAN><STRONG>The full key logic</STRONG>: used when we access the entity <STRONG>directly</STRONG> or by association inversed direction <STRONG>from child to parent</STRONG>.</SPAN></FONT></LI></UL><P><FONT face="arial,helvetica,sans-serif">While maintaining the buffer is primarily required for compositions, it may also be neccessary in cross-BO scenario where external associations are involved.</FONT></P><P><FONT face="arial,helvetica,sans-serif">Impact of key field data type on buffer handling:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif"><STRONG>Semantic key (e.g. character, numeric etc. fields)</STRONG>: you must handle entire set of the key fields for each level and the set may grow when you are moving dipper in RAP business object tree.</FONT></LI><LI><FONT face="arial,helvetica,sans-serif"><STRONG>GUID keys(raw16):</STRONG> you only need to process the only technical GUID field for reading, checking entity in the buffer tables.</FONT></LI></UL><P><FONT face="arial,helvetica,sans-serif"><STRONG>The full key representation.</STRONG></FONT><BR /><FONT face="arial,helvetica,sans-serif">This represents the <STRONG>complete primary key</STRONG> required to identify a specific instance.</FONT></P><TABLE border="1" width="100%"><TBODY><TR><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif"><STRONG>Level</STRONG></FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif"><STRONG>Semantic keys</STRONG></FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif"><STRONG>GUID keys</STRONG></FONT></TD></TR><TR><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">first node</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">FirstKey</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">FirstGuid</FONT></TD></TR><TR><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">second node</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">FirstKey, SecondKey</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">SecondGuid</FONT></TD></TR><TR><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">third node</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">FirstKey, SecondKey, ThirdKey</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">ThirdGuid</FONT></TD></TR><TR><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">fourth node</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">FirstKey, SecondKey, ThirdKey, FourthKey</FONT></TD><TD width="33.333333333333336%"><FONT face="arial,helvetica,sans-serif">FourthGuid</FONT></TD></TR></TBODY></TABLE><P><FONT face="arial,helvetica,sans-serif"><STRONG>The partial key representation.</STRONG></FONT><BR /><FONT face="arial,helvetica,sans-serif">This represents the <STRONG>keys of the imediate parent</STRONG>, used to fetch all associated children.&nbsp;</FONT></P><TABLE border="1" width="100%"><TBODY><TR><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif"><STRONG>Level</STRONG></FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif"><STRONG>Semantic keys</STRONG></FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif"><STRONG>GUID keys</STRONG></FONT></TD></TR><TR><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">first node</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">N/A</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">&nbsp;N/A</FONT></TD></TR><TR><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">second node</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">FirstKey</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">FirstGuid</FONT></TD></TR><TR><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">third node</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">FirstKey, SecondKey</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">SecondGuid</FONT></TD></TR><TR><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">fourth node</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">FirstKey, SecondKey, ThirdKey</FONT></TD><TD width="33.333333333333336%" height="30px"><FONT face="arial,helvetica,sans-serif">ThirdGuid</FONT></TD></TR></TBODY></TABLE><P><FONT face="arial,helvetica,sans-serif">Schematically it can be expressed in the following way:</FONT></P><pre class="lia-code-sample language-abap"><code>FULL KEY NOT GUID node / key field 1 / 1 2 / 1, 2 3 / 1, 2, 3 4 / 1, 2, 3, 4 GUID node / key field 1 / 1 2 / 2 3 / 3 4 / 4 PARENT KEY NOT GUID node / key field 1 / N/A 2 / 1 3 / 1, 2 4 / 1, 2, 3 GUID node / key field 1 / N/A 2 / 1 3 / 2 4 / 3 </code></pre><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Complex Data source</STRONG>.</U></FONT></P><P><FONT face="arial,helvetica,sans-serif">In a <STRONG>managed scenario</STRONG>, data source is defined as a <STRONG>persisted table</STRONG> in the BDEF. In an <STRONG>unmanaged scenario</STRONG>, the data source has a <STRONG>complex structure</STRONG> from which you load entries into the buffer and save entries from the buffer. 'Complex' means it can not be reduced to a single database table. It might be a <STRONG>BAPI</STRONG>, an <STRONG>HTTP response</STRONG>, a <STRONG>legacy API class</STRONG> or a <STRONG>combination</STRONG> of them.</FONT><BR /><FONT face="arial,helvetica,sans-serif">This complexity requires choosing an <STRONG>unmanaged implementation</STRONG>. You will also notice that you can not use keyword 'persistent table' in BDEF for <STRONG>unmanaged implementation type</STRONG>. And that is fair; your data source is not a just database table.</FONT></P><pre class="lia-code-sample language-abap"><code>METHOD prep_first_node_buffer. ***** ***** IF lt_keys_2_read IS NOT INITIAL. " SELECT * FROM zr_pru_1st_node " CALL EXTERNAL SOURCE VIA HTTP " CALL BAPI " CALL LEGACY API " UPLOAD FILE " COMBINATION OF THEM AND ETC. IF sy-subrc = 0. LOOP AT lt_entity_result ASSIGNING FIELD-SYMBOL(&lt;ls_result&gt;). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_first_node ASSIGNING FIELD-SYMBOL(&lt;ls_buffer&gt;). &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDLOOP. ENDIF. ENDIF. ENDMETHOD.</code></pre><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Buffer Components</STRONG></U></FONT></P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="3"><U><STRONG>Buffer flags</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">Each row of the <STRONG>entity buffer table</STRONG> may contain any flags you require, but the minimum necessary are<STRONG> 'changed'</STRONG> and <STRONG>'deleted'</STRONG> flags. When you initialize a buffer entry, <STRONG>both flags are false</STRONG>. When you update an entry, you setup the changed flag to true. When you delete an entry, you setup the delete flag to true. Optionally, during deletion, you may set both flags as true, but I don't prefer such way. Finally, in the method SAVE you will sort all buffer entries into two separate internal local tables: one for <STRONG>modifying database</STRONG>, another for <STRONG>deleting from the database</STRONG>.</FONT></P><pre class="lia-code-sample language-abap"><code>CLASS zpru_cl_example_buffer DEFINITION PUBLIC FINAL CREATE PUBLIC. ***** ***** TYPES: BEGIN OF ts_first_node, instance TYPE zr_pru_1st_node, ***** ***** changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_first_node. TYPES: BEGIN OF ts_second_node, instance TYPE zr_pru_2nd_node, ***** ***** changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_second_node. ***** ***** ENDCLASS.</code></pre><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="3"><U><STRONG>Buffer additional components</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">The <STRONG>entity buffer table</STRONG> row may contain components as <STRONG>CID</STRONG> for handling field <STRONG>%CID</STRONG>, and <STRONG>PID</STRONG> for field <STRONG>%PID</STRONG> field in late numbering scenarios. Since I am using a <STRONG>late nubmering scenario</STRONG>, I have added <STRONG>component FINAL</STRONG><SPAN><STRONG>_KEY</STRONG>&nbsp; to preserve the result from ADJUST_NUMBERS method.</SPAN></FONT></P><pre class="lia-code-sample language-abap"><code>CLASS zpru_cl_example_buffer DEFINITION PUBLIC FINAL CREATE PUBLIC. ***** ***** TYPES: BEGIN OF ts_first_node, instance TYPE zr_pru_1st_node, cid TYPE abp_behv_cid, pid TYPE abp_behv_pid, final_key TYPE ts_first_node_db_keys, ***** ***** END OF ts_first_node. TYPES: BEGIN OF ts_second_node, instance TYPE zr_pru_2nd_node, cid TYPE abp_behv_cid, pid TYPE abp_behv_pid, pidparent TYPE abp_behv_pid, final_key TYPE ts_second_node_db_keys, ***** ***** END OF ts_second_node. ***** ***** ENDCLASS.</code></pre><P>&nbsp;</P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="5"><U><STRONG>Generic pattern of usage.</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">Buffer handled in the following way:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif">In <STRONG>transactinal phase</STRONG> in method READ, CREATE, UPDATE, DELETE, RBA&nbsp; AND CBA:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">Prepare buffer using input keys using methods ZPRU_CL_EXAMPLE_BUFFER=&gt;PREP_FIRST_NODE_BUFFER</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">read, insert,&nbsp; update, delete(set deleted flag) entry from, in entity buffer table</FONT></LI></UL></LI><LI><FONT face="arial,helvetica,sans-serif">In <STRONG>save phase</STRONG>:</FONT><UL><LI><FONT face="arial,helvetica,sans-serif">Determine values for entries from entity buffer table in method FINALIZE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">Validate values for entries from entity buffer table in method CHECK_BEFORE_SAVE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">Save entries from entity buffer tables to complex data source in method SAVE</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">Clean-up buffer tables in method CLEANUP</FONT></LI></UL></LI></UL><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Buffer access</STRONG>.</U></FONT></P><P>From handling perspective <STRONG>transactinal buffer</STRONG> can be accesed <STRONG>directly</STRONG> and <STRONG>indirectly</STRONG> in your unmanaged implementation during different phase.</P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="3"><U><STRONG>Buffer access in Transactional phase.</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">Basically during<STRONG> transactional phase</STRONG> we can access buffer in two flawors in ABP class:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif"><STRONG>Direct access</STRONG> is used in such methods like read, read by association, create by association, create, update, delete(<STRONG>standard operations</STRONG>).</FONT></LI><LI><FONT face="arial,helvetica,sans-serif"><STRONG>Indirect access</STRONG> is used in such methods for instance feature, instance authorization, actions, functions and etc. via <STRONG>EML</STRONG> read, modify(<STRONG>non-standard operations</STRONG>)</FONT></LI></UL><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino"><U><STRONG>Buffer access in Save phase</STRONG></U></FONT></P><P><FONT face="tahoma,arial,helvetica,sans-serif"><FONT face="arial,helvetica,sans-serif">During <STRONG>save phase</STRONG> we access data <STRONG>directly from buffer</STRONG>, the main reason is that methods FINALIZE, CHECK_BEFORE_SAVE, ADJUST_NUMBERS, SAVE, CLEANUP and CLEANUP_FINALIZE are not provided with input entity keys. The only source of eventual keys to process is the buffer tables itself. Also we can use EML to read data taking keys from buffer tables.</FONT></FONT></P><P><FONT face="arial,helvetica,sans-serif"><STRONG>Types of access</STRONG> in save phase:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif">predominantly direct access in methods FINALIZE, CHECK_BEFORE_SAVE, ADJUST_NUMBERS, SAVE, CLEANUP and CLEANUP_FINALIZE.</FONT></LI><LI><FONT face="arial,helvetica,sans-serif">indirect access via EML read.</FONT></LI></UL><pre class="lia-code-sample language-abap"><code> " No input keys " To find out what to process we must have a look in the buffer. " Finalize execute determinations, be aware that determiantion for draft " and active instances are different things. Finalize is mainly " about active data methods FINALIZE changing !FAILED type DATA !REPORTED type DATA . " No input keys " This method for validation and again mainly for active data. methods CHECK_BEFORE_SAVE changing !FAILED type DATA !REPORTED type DATA . " input keys " This method will save active data to source of active data " Usually the data source is complex, not just one table or even two tables methods SAVE changing !REPORTED type DATA optional !FAILED type DATA optional .</code></pre><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Transactional buffer vs Draft buffer</STRONG>.</U></FONT></P><P><FONT face="arial,helvetica,sans-serif">If you business object has draft capabilities, don't conflate <STRONG>transactional buffer</STRONG> implemented by developer and <STRONG>draft buffer</STRONG> handled by managed runtime. They live <STRONG>in parallel</STRONG> and sometimes need to be synchronized via additional implementation for EDIT, ACTIVATE, DISCARD, RESUME.&nbsp; All in all draft processing is carried on by managed runtime despite that you have unmanaged implementation of business object.</FONT></P><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Operation aggregation.</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">Transactional buffer must handle <STRONG>operation aggregation</STRONG>. Operation aggregation means that user can create, update and update one more time, execute action <STRONG>in the same LUW,</STRONG> more over even <STRONG>in one EML statement</STRONG>. One more prominant example of operation aggregation is when user create, delete and then create again entry for RAP business object.</FONT></P><pre class="lia-code-sample language-abap"><code>*All CRUD operations must support aggreggation of operations. *Just for your undestanding there are a lot possible sequences like: *1. C 2. U 3. D 4. C + U 5. C + D 6. D + C 7. C + U + D 8. U + D + C and etc. *The following level of complexity is that operations can be repeate multiple *times for the same instance(set of key fields) *C + C + U + U + U + D and etc. *There are more caviats that you can think, eg. *C1 + D + C2 =&gt; create with some particalar fields, then mark it as deleted *and it is still in our buffer, then create again with the same key but *another set of data fields </code></pre><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="4"><U><STRONG>Delete vs Discard vs Remove entry from buffer.</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">So let's define couple moments:</FONT></P><UL><LI><FONT face="arial,helvetica,sans-serif"><STRONG>Delete</STRONG> means to set flag <STRONG>'deleted'</STRONG> in method DELETE of ABP pool class. Real deletion happens in method SAVE, based on this flag.</FONT></LI><LI><FONT face="arial,helvetica,sans-serif"><STRONG>Discard</STRONG> - basically the same as delete but it is handled by <STRONG>draft runtime</STRONG> and is <STRONG>provided out-of-box</STRONG>. Developer isn't responsible for discard implementation. We only can add <STRONG>additional implementation</STRONG> to provide additional logic for the method DISCARD.</FONT></LI><LI><FONT face="arial,helvetica,sans-serif"><STRONG>Remove</STRONG> - sometimes can happend, e.g. in the method CLEANUP&nbsp; or in the method CREATE&nbsp; during attempt to recreate entry with the same keys as previously marked as deleted(<STRONG>delete then create again</STRONG>).</FONT></LI></UL><P class="lia-align-center" style="text-align: center;"><FONT face="georgia,palatino" size="5"><U><STRONG>Unmanaged Transactional Buffer Blueprint</STRONG></U></FONT></P><P><FONT face="arial,helvetica,sans-serif">At last, we can conclude our research with the publication of the code of the buffer class, the so called <STRONG>unmanaged trasnactional buffer blueprint</STRONG>. You are welcom to utilize and adapt this code for your specific requirements.</FONT></P><pre class="lia-code-sample language-abap"><code>CLASS zpru_cl_example_buffer DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. TYPES: BEGIN OF ts_first_node_db_keys, firstkey TYPE zr_pru_1st_node-firstkey, END OF ts_first_node_db_keys. TYPES: BEGIN OF ts_second_node_db_keys, firstkey TYPE zr_pru_2nd_node-firstkey, secondkey TYPE zr_pru_2nd_node-secondkey, END OF ts_second_node_db_keys. TYPES: BEGIN OF ts_third_node_db_keys, firstkey TYPE zr_pru_3rd_node-firstkey, secondkey TYPE zr_pru_3rd_node-secondkey, thirdkey TYPE zr_pru_3rd_node-thirdkey, END OF ts_third_node_db_keys. TYPES: BEGIN OF ts_fourth_node_db_keys, firstkey TYPE zr_pru_4th_node-firstkey, secondkey TYPE zr_pru_4th_node-secondkey, thirdkey TYPE zr_pru_4th_node-thirdkey, fourthkey TYPE zr_pru_4th_node-fourthkey, END OF ts_fourth_node_db_keys. TYPES: BEGIN OF ts_first_node, instance TYPE zr_pru_1st_node, cid TYPE abp_behv_cid, pid TYPE abp_behv_pid, final_key TYPE ts_first_node_db_keys, changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_first_node. TYPES: BEGIN OF ts_second_node, instance TYPE zr_pru_2nd_node, cid TYPE abp_behv_cid, pid TYPE abp_behv_pid, pidparent TYPE abp_behv_pid, final_key TYPE ts_second_node_db_keys, changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_second_node. TYPES: BEGIN OF ts_third_node, instance TYPE zr_pru_3rd_node, cid TYPE abp_behv_cid, pid TYPE abp_behv_pid, pidparent TYPE abp_behv_pid, final_key TYPE ts_third_node_db_keys, changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_third_node. TYPES: BEGIN OF ts_fourth_node, instance TYPE zr_pru_4th_node, pid TYPE abp_behv_pid, pidparent TYPE abp_behv_pid, final_key TYPE ts_fourth_node_db_keys, changed TYPE abap_bool, deleted TYPE abap_bool, END OF ts_fourth_node. TYPES tt_first_node TYPE TABLE OF ts_first_node WITH EMPTY KEY. TYPES tt_second_node TYPE TABLE OF ts_second_node WITH EMPTY KEY. TYPES tt_third_node TYPE TABLE OF ts_third_node WITH EMPTY KEY. TYPES tt_fourth_node TYPE TABLE OF ts_fourth_node WITH EMPTY KEY. CLASS-DATA st_first_node TYPE tt_first_node. CLASS-DATA st_second_node TYPE tt_second_node. CLASS-DATA st_third_node TYPE tt_third_node. CLASS-DATA st_fourth_node TYPE tt_fourth_node. TYPES: BEGIN OF ts_first_node_keys. INCLUDE TYPE ts_first_node_db_keys. TYPES: END OF ts_first_node_keys. TYPES: BEGIN OF ts_second_node_keys. INCLUDE TYPE ts_second_node_db_keys. TYPES: full_key TYPE abap_bool, END OF ts_second_node_keys. TYPES: BEGIN OF ts_third_node_keys. INCLUDE TYPE ts_third_node_db_keys. TYPES: full_key TYPE abap_bool, END OF ts_third_node_keys. TYPES: BEGIN OF ts_fourth_node_keys. INCLUDE TYPE ts_fourth_node_db_keys. TYPES: full_key TYPE abap_bool, END OF ts_fourth_node_keys. TYPES tt_first_node_keys TYPE TABLE OF ts_first_node_keys WITH EMPTY KEY. TYPES tt_second_node_keys TYPE TABLE OF ts_second_node_keys WITH EMPTY KEY. TYPES tt_third_node_keys TYPE TABLE OF ts_third_node_keys WITH EMPTY KEY. TYPES tt_fourth_node_keys TYPE TABLE OF ts_fourth_node_keys WITH EMPTY KEY. CLASS-METHODS prep_first_node_buffer IMPORTING !keys TYPE tt_first_node_keys. CLASS-METHODS prep_second_node_buffer IMPORTING !keys TYPE tt_second_node_keys. CLASS-METHODS prep_third_node_buffer IMPORTING !keys TYPE tt_third_node_keys. CLASS-METHODS prep_fourth_node_buffer IMPORTING !keys TYPE tt_fourth_node_keys. ENDCLASS. CLASS zpru_cl_example_buffer IMPLEMENTATION. METHOD prep_first_node_buffer. DATA lt_keys_2_read LIKE keys. DATA lt_entity_result TYPE STANDARD TABLE OF zr_pru_1st_node WITH EMPTY KEY. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;ls_key&gt;). IF line_exists( zpru_cl_example_buffer=&gt;st_first_node[ instance-firstkey = &lt;ls_key&gt;-firstkey ] ). CONTINUE. ELSE. APPEND INITIAL LINE TO lt_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_key_2_read&gt;). &lt;ls_key_2_read&gt;-firstkey = &lt;ls_key&gt;-firstkey. ENDIF. ENDLOOP. IF lt_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_1st_node FOR ALL ENTRIES IN lt_keys_2_read WHERE firstkey = lt_keys_2_read-firstkey INTO TABLE lt_entity_result. IF sy-subrc = 0. LOOP AT lt_entity_result ASSIGNING FIELD-SYMBOL(&lt;ls_result&gt;). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_first_node ASSIGNING FIELD-SYMBOL(&lt;ls_buffer&gt;). &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDLOOP. ENDIF. ENDIF. ENDMETHOD. METHOD prep_second_node_buffer. DATA lt_full_keys_2_read LIKE keys. DATA lt_part_keys_2_read LIKE keys. DATA lt_full_entity_result TYPE STANDARD TABLE OF zr_pru_2nd_node WITH EMPTY KEY. DATA lt_part_entity_result TYPE STANDARD TABLE OF zr_pru_2nd_node WITH EMPTY KEY. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;ls_key_child&gt;). IF &lt;ls_key_child&gt;-full_key = abap_true. IF line_exists( zpru_cl_example_buffer=&gt;st_second_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey ] ). CONTINUE. ELSE. APPEND INITIAL LINE TO lt_full_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_full_key_2_read&gt;). &lt;ls_full_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. &lt;ls_full_key_2_read&gt;-secondkey = &lt;ls_key_child&gt;-secondkey. ENDIF. ELSE. IF line_exists( zpru_cl_example_buffer=&gt;st_first_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey ] ) AND VALUE #( zpru_cl_example_buffer=&gt;st_first_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey ]-deleted OPTIONAL ) IS NOT INITIAL. CONTINUE. ELSE. APPEND INITIAL LINE TO lt_part_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_part_key_2_read&gt;). &lt;ls_part_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. ENDIF. ENDIF. ENDLOOP. IF lt_full_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_2nd_node FOR ALL ENTRIES IN lt_full_keys_2_read WHERE firstkey = lt_full_keys_2_read-firstkey AND secondkey = lt_full_keys_2_read-secondkey INTO TABLE lt_full_entity_result. IF sy-subrc = 0. LOOP AT lt_full_entity_result ASSIGNING FIELD-SYMBOL(&lt;ls_result&gt;). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_second_node ASSIGNING FIELD-SYMBOL(&lt;ls_buffer&gt;). &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDLOOP. ENDIF. ENDIF. IF lt_part_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_2nd_node FOR ALL ENTRIES IN lt_part_keys_2_read WHERE firstkey = lt_part_keys_2_read-firstkey INTO TABLE lt_part_entity_result. IF sy-subrc = 0. LOOP AT lt_part_entity_result ASSIGNING &lt;ls_result&gt;. IF NOT line_exists( zpru_cl_example_buffer=&gt;st_second_node[ instance-firstkey = &lt;ls_result&gt;-firstkey instance-secondkey = &lt;ls_result&gt;-secondkey ] ). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_second_node ASSIGNING &lt;ls_buffer&gt;. &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDIF. ENDLOOP. ENDIF. ENDIF. ENDMETHOD. METHOD prep_third_node_buffer. DATA lt_full_keys_2_read LIKE keys. DATA lt_part_keys_2_read LIKE keys. DATA lt_full_entity_result TYPE STANDARD TABLE OF zr_pru_3rd_node WITH EMPTY KEY. DATA lt_part_entity_result TYPE STANDARD TABLE OF zr_pru_3rd_node WITH EMPTY KEY. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;ls_key_child&gt;). IF &lt;ls_key_child&gt;-full_key = abap_true. IF line_exists( zpru_cl_example_buffer=&gt;st_third_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey instance-thirdkey = &lt;ls_key_child&gt;-thirdkey ] ). CONTINUE. ELSE. APPEND INITIAL LINE TO lt_full_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_full_key_2_read&gt;). &lt;ls_full_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. &lt;ls_full_key_2_read&gt;-secondkey = &lt;ls_key_child&gt;-secondkey. &lt;ls_full_key_2_read&gt;-thirdkey = &lt;ls_key_child&gt;-thirdkey. ENDIF. ELSE. IF line_exists( zpru_cl_example_buffer=&gt;st_second_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey ] ) AND VALUE #( zpru_cl_example_buffer=&gt;st_second_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey ]-deleted OPTIONAL ) IS NOT INITIAL. CONTINUE. ELSE. APPEND INITIAL LINE TO lt_part_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_part_key_2_read&gt;). &lt;ls_part_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. ENDIF. ENDIF. ENDLOOP. IF lt_full_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_3rd_node FOR ALL ENTRIES IN _full_keys_2_read WHERE firstkey = lt_full_keys_2_read-firstkey AND secondkey = lt_full_keys_2_read-secondkey AND thirdkey = lt_full_keys_2_read-thirdkey INTO TABLE lt_full_entity_result. IF sy-subrc = 0. LOOP AT lt_full_entity_result ASSIGNING FIELD-SYMBOL(&lt;ls_result&gt;). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_third_node ASSIGNING FIELD-SYMBOL(&lt;ls_buffer&gt;). &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDLOOP. ENDIF. ENDIF. IF lt_part_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_3rd_node FOR ALL ENTRIES IN lt_part_keys_2_read WHERE firstkey = lt_part_keys_2_read-firstkey AND secondkey = lt_part_keys_2_read-secondkey INTO TABLE lt_part_entity_result. IF sy-subrc = 0. LOOP AT lt_part_entity_result ASSIGNING &lt;ls_result&gt;. IF NOT line_exists( zpru_cl_example_buffer=&gt;st_third_node[ instance-firstkey = &lt;ls_result&gt;-firstkey instance-secondkey = &lt;ls_result&gt;-secondkey instance-thirdkey = &lt;ls_result&gt;-thirdkey ] ). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_third_node ASSIGNING &lt;ls_buffer&gt;. &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDIF. ENDLOOP. ENDIF. ENDIF. ENDMETHOD. METHOD prep_fourth_node_buffer. DATA lt_full_keys_2_read LIKE keys. DATA lt_part_keys_2_read LIKE keys. DATA lt_full_entity_result TYPE STANDARD TABLE OF zr_pru_4th_node WITH EMPTY KEY. DATA lt_part_entity_result TYPE STANDARD TABLE OF zr_pru_4th_node WITH EMPTY KEY. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;ls_key_child&gt;). IF &lt;ls_key_child&gt;-full_key = abap_true. IF line_exists( zpru_cl_example_buffer=&gt;st_fourth_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey instance-thirdkey = &lt;ls_key_child&gt;-thirdkey instance-fourthkey = &lt;ls_key_child&gt;-fourthkey ] ). CONTINUE. ELSE. APPEND INITIAL LINE TO lt_full_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_full_key_2_read&gt;). &lt;ls_full_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. &lt;ls_full_key_2_read&gt;-secondkey = &lt;ls_key_child&gt;-secondkey. &lt;ls_full_key_2_read&gt;-thirdkey = &lt;ls_key_child&gt;-thirdkey. &lt;ls_full_key_2_read&gt;-fourthkey = &lt;ls_key_child&gt;-fourthkey. ENDIF. ELSE. IF line_exists( zpru_cl_example_buffer=&gt;st_third_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey instance-thirdkey = &lt;ls_key_child&gt;-thirdkey ] ) AND VALUE #( zpru_cl_example_buffer=&gt;st_third_node[ instance-firstkey = &lt;ls_key_child&gt;-firstkey instance-secondkey = &lt;ls_key_child&gt;-secondkey instance-thirdkey = &lt;ls_key_child&gt;-thirdkey ]-deleted OPTIONAL ) IS NOT INITIAL. CONTINUE. ELSE. APPEND INITIAL LINE TO lt_part_keys_2_read ASSIGNING FIELD-SYMBOL(&lt;ls_part_key_2_read&gt;). &lt;ls_part_key_2_read&gt;-firstkey = &lt;ls_key_child&gt;-firstkey. ENDIF. ENDIF. ENDLOOP. IF lt_full_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_4th_node FOR ALL ENTRIES IN lt_full_keys_2_read WHERE firstkey = lt_full_keys_2_read-firstkey AND secondkey = lt_full_keys_2_read-secondkey AND thirdkey = lt_full_keys_2_read-thirdkey AND fourthkey = lt_full_keys_2_read-fourthkey INTO TABLE lt_full_entity_result. IF sy-subrc = 0. LOOP AT lt_full_entity_result ASSIGNING FIELD-SYMBOL(&lt;ls_result&gt;). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_fourth_node ASSIGNING FIELD-SYMBOL(&lt;ls_buffer&gt;). &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDLOOP. ENDIF. ENDIF. IF lt_part_keys_2_read IS NOT INITIAL. SELECT * FROM zr_pru_4th_node FOR ALL ENTRIES IN lt_part_keys_2_read WHERE firstkey = lt_part_keys_2_read-firstkey AND secondkey = lt_part_keys_2_read-secondkey AND thirdkey = lt_part_keys_2_read-thirdkey INTO TABLE lt_part_entity_result. IF sy-subrc = 0. LOOP AT lt_part_entity_result ASSIGNING &lt;ls_result&gt;. IF NOT line_exists( zpru_cl_example_buffer=&gt;st_fourth_node[ instance-firstkey = &lt;ls_result&gt;-firstkey instance-secondkey = &lt;ls_result&gt;-secondkey instance-thirdkey = &lt;ls_result&gt;-thirdkey instance-fourthkey = &lt;ls_result&gt;-fourthkey ] ). APPEND INITIAL LINE TO zpru_cl_example_buffer=&gt;st_fourth_node ASSIGNING &lt;ls_buffer&gt;. &lt;ls_buffer&gt;-instance = &lt;ls_result&gt;. ENDIF. ENDLOOP. ENDIF. ENDIF. ENDMETHOD. ENDCLASS.</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P> 2026-01-19T12:23:34.134000+01:00 https://community.sap.com/t5/financial-management-blog-posts-by-sap/new-events-for-outbound-nota-fiscal/ba-p/14311133 New Events for Outbound Nota Fiscal 2026-01-20T14:48:41.847000+01:00 natalian https://community.sap.com/t5/user/viewprofilepage/user-id/1841863 <P><SPAN>Hi everyone!&nbsp;</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Today, I would like to share with you some impactful insights directly from an SAP Note, which outlines a streamlined approach for sending&nbsp;the&nbsp;events listed in&nbsp;the&nbsp;</SPAN><STRONG><SPAN>NF-e Technical Note 2025.002 v1.30</SPAN></STRONG><SPAN>, published October&nbsp;2025.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>You can implement these changes in the outbound&nbsp;invoicing&nbsp;option&nbsp;for Brazil by following the instructions on SAP Note </SPAN><A href="https://me.sap.com/notes/3692197" target="_blank" rel="noopener noreferrer"><SPAN>3692197</SPAN></A><SPAN>&nbsp;and SAP Note&nbsp;</SPAN><A href="https://me.sap.com/notes/3689265" target="_blank" rel="noopener noreferrer"><SPAN>3689265</SPAN></A><SPAN>.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Check out the latest updates and features in our What's New session on the SAP Help Portal:</SPAN><SPAN>&nbsp;</SPAN></P><UL><LI><SPAN>SAP S/4HANA: </SPAN><A href="https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/83fb257602634259bf40b22d80c1f563/c5573bcbf5604098bd115b37bf075271.html" target="_blank" rel="noopener noreferrer"><SPAN>New Events for Outbound Nota Fiscal</SPAN></A><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>SAP ERP: </SPAN><A href="https://help.sap.com/docs/SAP_ERP/063e7e5f4d7f4fc0be08565793a9b941/c5573bcbf5604098bd115b37bf075271.html" target="_blank" rel="noopener noreferrer"><SPAN>New Events for Outbound Nota Fiscal</SPAN></A><SPAN>&nbsp;</SPAN></LI></UL><P><STRONG><SPAN>The Process</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>To send these events, you need to create a specific structure, as described in the "</SPAN><A href="https://www.nfe.fazenda.gov.br/portal/listaConteudo.aspx?tipoConteudo=04BIflQt1aY=&amp;AspxAutoDetectCookieSupport=1" target="_blank" rel="noopener nofollow noreferrer"><SPAN>Manual&nbsp;da SEFAZ"</SPAN></A><SPAN>.&nbsp;You&nbsp;should&nbsp;create the new structure through&nbsp;the&nbsp;SEND_GENERIC_EVENT method&nbsp;from the CL_NFE_CLOUD_NFE_PROCESSOR class. This effectively sends the events using the IS_GENERIC_EVENT parameter, which is essential for declaring the structure.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>You&nbsp;have to&nbsp;name this structure as&nbsp;ZNFE_MAP_EVENT_XXXXXX.&nbsp;You replace the XXXXXX for the number of supported events from the NF-e Technical Note 2025.002 v1.30.&nbsp;For&nbsp;example:&nbsp;ZNFE_MAP_EVENT_112110.&nbsp;</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>In&nbsp;this structure,&nbsp;you'll&nbsp;find control fields and event-specific fields that&nbsp;are mapped directly to the XML event.&nbsp;You&nbsp;have&nbsp;to&nbsp;build the DET_EVENTO structure,&nbsp;which can vary depending on the type of event.&nbsp;The field names differ between the backend system and their appearance in the cloud solution. Check the following example:&nbsp;</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>The structure of the event&nbsp;112110 (Informação&nbsp;de&nbsp;efetivo&nbsp;pagamento&nbsp;integral para&nbsp;liberar&nbsp;crédito&nbsp;presumido&nbsp;do&nbsp;adquirente) is denoted as ZNFE_MAP_EVENT_112110.&nbsp;This structure has the following string fields&nbsp;and their equivalent in the cloud solution,&nbsp;following the rules of name conversion:</SPAN><SPAN>&nbsp;</SPAN></P><UL><LI><SPAN>ATTR_VERSAO -&gt;&nbsp;converted to a__versao&nbsp;to create the XML&nbsp;(you can check the rule to create XML attributes instead of elements in SAP Note&nbsp;</SPAN><A href="https://me.sap.com/notes/3692197" target="_blank" rel="noopener noreferrer"><SPAN>3692197</SPAN></A><SPAN>)</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>DESC_EVENTO -&gt;&nbsp;descEvento</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>C_ORGAO_AUTOR -&gt;&nbsp;cOrgaoAutor</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>TP_AUTOR -&gt;&nbsp;tpAutor</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>VER_APLIC -&gt;&nbsp;verAplic</SPAN><SPAN>&nbsp;</SPAN></LI></UL><P><SPAN>Check the XML file obtained after the name conversion. To download the XML file, follow the steps mentioned in SAP Note </SPAN><A href="https://me.sap.com/notes/3692197" target="_blank" rel="noopener noreferrer"><SPAN>3692197</SPAN></A><SPAN>.&nbsp;</SPAN><SPAN>&nbsp;</SPAN></P><pre class="lia-code-sample language-markup"><code>&lt;detEvento versao="1"&gt; &lt;descEvento&gt;Informação de efetivo pagamento integral para liberar crédito presumido do adquirente&lt;/descEvento&gt; &lt;cOrgaoAutor&gt;35&lt;/cOrgaoAutor&gt; &lt;tpAutor&gt;1&lt;/tpAutor&gt; &lt;verAplic&gt;1&lt;/verAplic&gt; &lt;indQuitacao&gt;1&lt;/indQuitacao&gt; &lt;/detEvento&gt; </code></pre><P><STRONG><SPAN>DET_EVENTO Structure Declaration</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>Create the&nbsp;structure &nbsp;ZNFE_MAP_EVENT_112110.&nbsp;Ensure&nbsp;the structure&nbsp;matches the following definition:</SPAN><SPAN>&nbsp;</SPAN></P><pre class="lia-code-sample language-abap"><code>TYPES: BEGIN OF ZNFE_MAP_EVENT_112110, a__versao TYPE string, " XML Attribute desc_evento TYPE string, c_orgao_autor TYPE string, tp_autor TYPE string, ver_aplic TYPE string, ind_quitacao TYPE string, END OF ZNFE_MAP_EVENT_112110. </code></pre><P><STRONG><SPAN>Populating DET_EVENTO</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>You populate the&nbsp;DET_EVENTO &nbsp;using&nbsp;assignment based on input parameters of the program.&nbsp;Check the following example:</SPAN><SPAN>&nbsp;</SPAN></P><pre class="lia-code-sample language-abap"><code>DATA : ls_event_112110 TYPE ZNFE_MAP_EVENT_112110. ls_event_112110-a__versao = p_ver. " Version - XML attribute ls_event_112110-desc_evento = p_desc. " Event description ls_event_112110-c_orgao_autor = p_orgaut. " Author organization code ls_event_112110-tp_autor = p_tpaut. " Type of authority ls_event_112110-ver_aplic = p_verapp. " Application version ls_event_112110-ind_quitacao = p_indqui. " Settlement indicator</code></pre><P><STRONG><SPAN>Steps to Send a Generic Event</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><U>Step 1: Declare and Populate IS_GENERIC_EVENT&nbsp;</U></P><P><SPAN>The IS_GENERIC_EVENT structure&nbsp;contains&nbsp;high-level control fields&nbsp;required&nbsp;for all types of events, including details such as issuing state, issuer's CNPJ, and access key (P_ACCKEY). Use the following template to populate the structure:</SPAN><SPAN>&nbsp;</SPAN></P><pre class="lia-code-sample language-abap"><code>DATA : ls_generic_event TYPE nfe_cloud_nfe_map_gnrc_evt. ls_generic_event-uuid = lo_uuid_generator-&gt;generate_uuid( ). " Unique identifier ls_generic_event-authorize_uuid = p_authid. " Reference UUID ls_generic_event-issuing_state = p_state. " State code ls_generic_event-environment_type = 'HOMOLOGATION'. " Environment ls_generic_event-issuing_type = 'NORMAL'. " Issuing type ls_generic_event-issuer_identifier = p_issuer. " Issuer CNPJ ls_generic_event-receiver_identifier = '74544297000192'. " Receiver CNPJ </code></pre><P><U>Step 2: Declare and Populate Specific DET_EVENTO&nbsp;</U></P><P><SPAN>Based on the event type (P_TYPE), decide the specific structure for DET_EVENTO. For example:</SPAN><SPAN>&nbsp;</SPAN></P><pre class="lia-code-sample language-abap"><code>If P_TYPE = '112110', use the predefined structure ZNFE_MAP_EVENT_112110: DATA : ls_event_112110 TYPE ZNFE_MAP_EVENT_112110. ls_event_112110-a__versao = p_ver. " Attributes mapped as XML attributes ls_event_112110-desc_evento = p_desc. ls_event_112110-c_orgao_autor = p_orgaut. ls_event_112110-tp_autor = p_tpaut. ls_event_112110-ver_aplic = p_verapp. ls_event_112110-ind_quitacao = p_indqui. ls_generic_event-event_info-det_evento-&gt;* = ls_event_112110. " Assigning DET_EVENTO structure </code></pre><P><U>Step 3: Send the Event&nbsp;</U></P><P>Invoke the SEND_GENERIC_EVENT method:</P><pre class="lia-code-sample language-abap"><code>TRY. ls_result = lo_processor-&gt;send_generic_event( is_generic_event = ls_generic_event is_company_definition = ls_company_defition ). CATCH cx_nfe_cloud_invalid_value INTO lx_invalid_value. lx_invalid_value-&gt;raise_message( ). RETURN. ENDTRY. </code></pre><P><STRONG><SPAN>Checking Event Status</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>To verify the status of sent events, follow these steps:</SPAN><SPAN>&nbsp;</SPAN></P><OL><LI><STRONG><SPAN>Service Locator:</SPAN></STRONG><SPAN>&nbsp;Use CREATE_SERVICE_LOCATOR_OBJECT from the CL_J_1BNFE_CF_MONITOR class.</SPAN><SPAN>&nbsp;</SPAN></LI></OL><OL><LI><STRONG><SPAN>Service Type Parameter:</SPAN></STRONG><SPAN>&nbsp;Reference C_SERVICE_EVENT_STATUS from CL_J_1BNFE_CF_CONSTANT.</SPAN><SPAN>&nbsp;</SPAN></LI></OL><OL><LI><STRONG><SPAN>Map Events and Generate JSON:</SPAN></STRONG><SPAN>&nbsp;Utilize&nbsp;the STRUCTURE_SERIALIZATION method from CL_J_1BNFE_CF_EVENT_UPDATE.</SPAN><SPAN>&nbsp;</SPAN></LI></OL><OL><LI><STRONG><SPAN>Client and OA2C Creation:</SPAN></STRONG><SPAN>&nbsp;Use SET_REQUEST_JSON and SEND_REQUEST_TO_CLOUD methods from CL_J_1BNFE_CF_SERVICE_COMM.</SPAN><SPAN>&nbsp;</SPAN></LI></OL><OL><LI><STRONG><SPAN>Transform JSON Response:</SPAN></STRONG><SPAN>&nbsp;Apply GET_RESPONSE_FROM_CLOUD to convert the response into an NF-e format.</SPAN><SPAN>&nbsp;</SPAN></LI></OL><OL><LI><STRONG><SPAN>Develop Response Structure:</SPAN></STRONG><SPAN>&nbsp;EVENT_TABLE_DESERIALIZATION method helps integrate this into an NF-e structure.</SPAN><SPAN>&nbsp;</SPAN></LI></OL><P><STRONG><SPAN>Building Your Application</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>Beyond these steps,&nbsp;you'll&nbsp;need to develop or extend your applications to:</SPAN><SPAN>&nbsp;</SPAN></P><UL><LI><SPAN>Fill in necessary event data.</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>Trigger creation and submission based on business processes.</SPAN><SPAN>&nbsp;</SPAN></LI></UL><UL><LI><SPAN>Implement error handling, logging, and&nbsp;monitoring&nbsp;according to&nbsp;your compliance standards.</SPAN><SPAN>&nbsp;</SPAN></LI></UL><P><SPAN>That's&nbsp;a wrap for today! I hope this guide serves as a handy reference for anyone navigating the intricacies of sending events in SAP.&nbsp;</SPAN><SPAN>Stay tuned for more insights and happy coding!</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Until next time,</SPAN></P><P><SPAN>Natália</SPAN></P><P><SPAN>SAP e-Invoicing Application Engineer</SPAN></P><P><SPAN>&nbsp;</SPAN></P> 2026-01-20T14:48:41.847000+01:00 https://community.sap.com/t5/technology-blog-posts-by-sap/your-2026-roadmap-to-getting-started-with-abap-ai-and-abap-1/ba-p/14312060 Your 2026 Roadmap to Getting Started with ABAP AI and ABAP-1 2026-01-21T18:01:36.956000+01:00 JanMatthes https://community.sap.com/t5/user/viewprofilepage/user-id/194386 <P data-unlink="true"><A title="ABAP AI Capabilities" href="https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/joule-for-developers-abap-ai-capabilities-f14ebffef77b41bfb0746c33dcb70e84" target="_blank" rel="noopener noreferrer"><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="ABAP_AI.png" style="width: 200px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/363821iFBD41BCBF30A65A8/image-size/small?v=v2&amp;px=200" role="button" title="ABAP_AI.png" alt="ABAP_AI.png" /></span></A>The era of "Wait and See" for AI in ABAP development is officially over. With the general availability of <STRONG>Joule for Developers (J4D)</STRONG> and the <A href="https://www.linkedin.com/posts/sonjalienard_introducing-the-next-era-of-abap-development-activity-7391805653905993728-J9a-?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAAAAwC8YBn3fP-40jJLXucycHYaj7szVogRw" target="_blank" rel="noopener nofollow noreferrer">planned availability of ABAP agentic AI frameworks in 2026</A>,&nbsp; the question isn't <EM>if</EM> you should use AI, but <EM>where</EM> you should start.&nbsp;</P><P data-unlink="true"><STRONG>The "Start Here" Recommendation:&nbsp;&nbsp;</STRONG>For 90% of developers, the best starting point is <STRONG><SPAN class=""><SPAN><A class="" href="https://www.sap.com/products/erp/s4hana-cloud-public-edition-joule-for-developers-abap-ai-capabilities.html" target="_blank" rel="noopener noreferrer">SAP Joule for Developers</A></SPAN></SPAN></STRONG> integrated within <STRONG>ABAP Development Tools (ADT) for Eclipse</STRONG>. In addition you can also experiment with the first versions of <A href="https://help.sap.com/docs/sap-ai-core/generative-ai/sap-abap-1?locale=en-US&amp;version=LATEST" target="_blank" rel="noopener noreferrer">ABAP-1 model to <STRONG>analyze and explain code</STRONG></A> on your own - but be aware that this is <STRONG>currently not for code generation </STRONG>and only for those which want to be independent of J4D<STRONG>.</STRONG> Therefore starting with J4D is the fastest but also the most powerful way to start with ABAP AI.</P><DIV class="">&nbsp;</DIV><DIV class=""><STRONG>Why should I start with Joule for Developers (J4D)?</STRONG></DIV><UL class=""><LI><SPAN class=""><STRONG>Contextual Intelligence:</STRONG> Unlike generic LLMs, Joule for Developers is additionally trained on over <STRONG>250 million lines of proprietary SAP code</STRONG> and is aware of your specific <STRONG>ABAP Cloud context.</STRONG> In general&nbsp;J2D is powered by a combination of third-party foundation models (e.g. OpenAI, Gemini, Anthropic, Mistral AI), alongside SAP-centric models like the LLMs, trained specifically on ABAP and purpose-built for cloud-based SAP development.</SPAN></LI><LI><SPAN class=""><STRONG>It’s Free (For Now):</STRONG> SAP has extended the free promotional period for Joule for Developers until <STRONG>September 2026</STRONG>.</SPAN></LI><LI><SPAN class=""><STRONG>Native Skills:</STRONG> It handles predictive code generation (e.g. RAP generation), "Explain" skills for legacy code, and unit test generation directly within your IDE. So it can do way more then ABAP-1 right now.</SPAN></LI><LI><SPAN class=""><STRONG>J4D&nbsp;</STRONG>is out of the box <STRONG>integrated in Eclipse ADT.</STRONG></SPAN></LI></UL><DIV class=""><STRONG>The Three Paths for ABAP AI Evolution:</STRONG></DIV><DIV class=""><STRONG>1. The Standard Path: Joule for Developers in ADT</STRONG></DIV><UL class=""><LI><SPAN class=""><STRONG>Best for:</STRONG> Daily coding, documentation, and unit testing.</SPAN></LI><LI><SPAN class=""><STRONG>Action:</STRONG> Request access through your administrator (Material 8019124 for customers and 8019541 for partners) and activate it in ADT.</SPAN></LI></UL><DIV class=""><STRONG>2. The Innovation Path: ABAP AI SDK &amp; BTP Free Tier</STRONG></DIV><UL class=""><LI><SPAN class=""><STRONG>Best for:</STRONG> Building your own AI-powered business applications (e.g., automated invoice processing).</SPAN></LI><LI><P>The <STRONG>ABAP AI SDK is our reuse library that enables you to integrate Large Language Models (LLMs) and generative AI</STRONG> features directly into your SAP business applications with ABAP. So it is the&nbsp;"AI toolbox," allowing you to build intelligent applications with business context in the ABAP stack.&nbsp;The ABAP AI SDK is available in:</P><UL><LI>SAP BTP ABAP Environment&nbsp;</LI><LI>SAP S/4HANA Cloud Public Edition&nbsp;</LI><LI>SAP S/4HANA Cloud Private Edition and OnPrem as of release 2025 via standard delivery.</LI><LI>S/4 HANA private cloud version and on-premise 2021 onwards are supported via Transport-based Correction Instructions (TCI), see details in&nbsp;<A href="https://me.sap.com/notes/3513374" target="_blank" rel="noopener noreferrer">SAP Note 3513374</A>.</LI></UL><P>Here you find more details on the AI SDK:&nbsp;</P><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="AI_SDK.jpg" style="width: 639px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/378553iEF75CA6522B2E107/image-dimensions/639x347?v=v2" width="639" height="347" role="button" title="AI_SDK.jpg" alt="AI_SDK.jpg" /></span></LI></UL></LI><LI>&nbsp;<UL><LI><A href="https://help.sap.com/docs/abap-ai/generative-ai-in-abap-cloud/availability" target="_blank" rel="noopener noreferrer">https://help.sap.com/docs/abap-ai/generative-ai-in-abap-cloud/availability</A></LI><LI><A href="https://community.sap.com/t5/artificial-intelligence-blogs-posts/abap-meets-ai-my-hands-on-experience-with-sap-s-abap-sdk-for-llm/ba-p/14285453" target="_blank">https://community.sap.com/t5/artificial-intelligence-blogs-posts/abap-meets-ai-my-hands-on-experience-with-sap-s-abap-sdk-for-llm/ba-p/14285453</A></LI></UL></LI><LI><SPAN class=""><STRONG>Action:</STRONG> Use the <STRONG>SAP BTP Free Tier</STRONG> to access the Generative AI Hub and the <STRONG>ABAP AI SDK</STRONG> to connect your custom ABAP code to external foundation models.</SPAN></LI></UL><DIV class=""><STRONG>3. The Modernization Path: VS Code with ABAP Cloud (Roadmap Q2/2026)</STRONG></DIV><UL class=""><LI><SPAN class=""><STRONG>Best for:</STRONG> Developers looking for a lightweight, file-based experience and for those which want to be the first to leverage agentic ABAP AI in side-by-side approach.</SPAN></LI><LI><STRONG>Action</STRONG>: Explore the new side-by-side ABAP Cloud Extension for <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/introducing-the-next-era-of-abap-development/ba-p/14260522" target="_blank">VS Code (GA planned for Q2 2026) with built-in Agentic AI</A> assistance powered by an <STRONG>ABAP MCP server</STRONG>. This will support a <STRONG>broader range of&nbsp;SAP S/4HANA Private Editions</STRONG> and provide <STRONG>faster update cycles</STRONG>.</LI></UL><DIV class=""><STRONG>Key Takeaway for 2026:</STRONG><BR />Don't get bogged down trying to "prompt engineer" experimental models like ABAP-1 for production code generation. Instead, leverage <STRONG>Joule for Developers</STRONG>&nbsp;mature "Explain" and "Generate" skills to <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/custom-code-migration-to-sap-s-4hana-powered-by-sap-joule-for-developers/ba-p/14329094" target="_blank">maintain a <STRONG>Clean Core</STRONG> and accelerate your migration to SAP S/4HANA.</A></DIV><P><STRONG>Here you can learn more:</STRONG></P><OL><LI><P><SPAN class=""><A class="" href="https://community.sap.com/t5/technology-blog-posts-by-sap/sap-joule-for-developers-expands-to-private-cloud-accelerating-abap/ba-p/14237958" target="_blank">SAP Joule for Developers (J4D) Expands to Private Cloud: Accelerating ABAP Innovation and Transformation </A></SPAN></P></LI><LI><A href="https://community.sap.com/t5/technology-blog-posts-by-sap/abap-ai-revolution-accelerates-the-abap-developer-who-built-enterprise-apps/ba-p/14216073" target="_blank"><SPAN class="">ABAP AI Revolution Accelerates: The ABAP Developer Who Built Enterprise Apps in Minutes </SPAN></A></LI><LI><A href="https://community.sap.com/t5/technology-blog-posts-by-sap/introducing-the-next-era-of-abap-development/ba-p/14260522" target="_blank"><SPAN class="">Joule for Developers and ABAP AI capabilities are coming to SAP S/4HANA Private Edition 2021, 2022, and 2023</SPAN></A></LI><LI><SPAN class="">Public Roadmap: <A href="https://help.sap.com/docs/abap-cross-product/roadmap-info/genai" target="_blank" rel="noopener noreferrer">SAP Help</A> / <A href="https://roadmaps.sap.com/board?PRODUCT=73554900100800001562&amp;PRODUCT=73555000100800001164&amp;range=CURRENT-LAST" target="_blank" rel="noopener noreferrer">SAP Roadmap Explorer</A></SPAN></LI><LI><A href="https://community.sap.com/t5/technology-blog-posts-by-sap/sap-joule-for-developers-abap-ai-capabilities-for-sap-s-4hana-cloud-private/ba-p/14236954" target="_blank"><SPAN class="">Step-by-step guide how to activate SAP Joule for Developers, ABAP AI capabilities for your SAP S/4HANA Cloud Private Edition</SPAN></A></LI><LI><SPAN class=""><SPAN><A href="https://community.sap.com/t5/technology-blog-posts-by-sap/joule-for-developers-with-sap-s-4hana-public-cloud-edition-setup-guide/ba-p/14209989" target="_blank">Joule for Developers (J4D) for S/4HANA Public Cloud Setup Guide</A></SPAN></SPAN></LI><LI><A href="https://discovery-center.cloud.sap/search/abap%20ai" target="_blank" rel="noopener nofollow noreferrer"><SPAN class=""><SPAN>SAP ABAP AI Discovery Center</SPAN></SPAN></A></LI><LI><SPAN class=""><SPAN><A class="" href="https://discovery-center.cloud.sap/search/Free-tier" target="_blank" rel="noopener nofollow noreferrer">SAP BTP Discovery Center (Free Tier Services)</A></SPAN></SPAN></LI><LI><SPAN class=""><SPAN><A href="https://community.sap.com/t5/technology-blog-posts-by-sap/custom-code-migration-to-sap-s-4hana-powered-by-sap-joule-for-developers/ba-p/14329094" target="_blank">Custom code migration to SAP S/4HANA powered by SAP Joule for Developers, ABAP AI capabilities</A> </SPAN></SPAN></LI><LI><A href="http://www.youtube.com/playlist?list=PL6RpkC85SLQAt9lvPw0gF4E3nwbJD0EUe" target="_blank" rel="noopener nofollow noreferrer"><SPAN class=""><SPAN>YouTube playlist for Joule for Developers (J4D)</SPAN></SPAN></A></LI><LI><A href="https://help.sap.com/docs/abap-ai" target="_blank" rel="noopener noreferrer"><SPAN class=""><SPAN>Joule for Developers Help (J4D)</SPAN></SPAN></A></LI><LI><A href="https://github.com/SAP-samples/abap-platform-rap120" target="_blank" rel="noopener nofollow noreferrer">Build SAP Fiori Apps with ABAP Cloud and SAP Joule for developers (RAP120)</A>&nbsp;</LI><LI><A href="https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/joule-for-developers-abap-ai-capabilities-f14ebffef77b41bfb0746c33dcb70e84" target="_blank" rel="noopener noreferrer"><SPAN class=""><SPAN>ADT Eclipse AI Capabilities Help</SPAN></SPAN></A></LI><LI><SPAN class=""><SPAN><A class="" href="https://help.sap.com/docs/abap-ai/generative-ai-in-abap-cloud/set-up-abap-ai-sdk-powered-by-intelligent-scenario-lifecycle-management" target="_blank" rel="noopener noreferrer">ABAP AI SDK Help</A></SPAN></SPAN></LI><LI><A href="https://help.sap.com/docs/sap-ai-core/generative-ai/sap-abap-1?locale=en-US&amp;version=LATEST" target="_blank" rel="noopener noreferrer"><SPAN class="">ABAP-1 Help</SPAN></A></LI></OL><P data-unlink="true"><SPAN class="">More high-level insights about <A href="https://www.sap.com/sea/products/artificial-intelligence/joule-for-developers.html" target="_blank" rel="noopener noreferrer">Joule for Developers/ABAP AI</A> and <A href="https://www.sap.com/products/technology-platform/abap/environment.html" target="_blank" rel="noopener noreferrer">ABAP platform can be found&nbsp;here</A>&nbsp;. Here you find <A href="https://www.sap.com/products/artificial-intelligence/sap-abap.html" target="_blank" rel="noopener noreferrer">more on ABAP-&nbsp;1</A>,</SPAN></P> 2026-01-21T18:01:36.956000+01:00 https://community.sap.com/t5/enterprise-architecture-blog-posts/creating-an-interactive-editable-alv-in-abap-with-header-item-crud/ba-p/14116499 Creating an Interactive Editable ALV in ABAP with Header-Item CRUD Functionality 2026-01-24T04:59:44.641000+01:00 Naveennani8523 https://community.sap.com/t5/user/viewprofilepage/user-id/1800750 <pre class="lia-code-sample language-abap"><code></code></pre><P>In this blog post, we will explore a powerful ABAP implementation of an editable ALV using CL_GUI_ALV_GRID. This solution provides:</P><UL><LI>Interactive two-screen design (Header &amp; Item)</LI><LI>Double-click to drill down from header to item</LI><LI>Row-based editing using LVC_ROWMARK</LI><LI>Field-level edit control via CELLTAB</LI><LI>Full CRUD operations (Create, Read, Update, Delete) for both header and item data</LI></UL><H2 id="toc-hId-1731461697"><span class="lia-unicode-emoji" title=":house:">🏠</span> Scenario</H2><P>We use two custom database tables:</P><UL><LI>Custom Table → Delivery Header Data (VBELN, ERNAM, ERDAT, VSTEL, VKORG)</LI><LI>Custom Table → Delivery Item Data (VBELN, POSNR, MATNR, WERKS)</LI></UL><P>The goal is to allow users to edit only selected rows, protect primary key fields, and manage entries interactively.</P><H3 id="toc-hId-1664030911">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <STRONG>Table Declarations</STRONG></H3><P>TABLES?</P><UL><LI>&nbsp;Custom transparent table containing delivery header data.</LI><LI>Custom transparent table for delivery item data.</LI><LI>These tables are used to fetch and store ALV grid data.</LI></UL><H3 id="toc-hId-1467517406"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>2. Class Forward Declaration</STRONG></H3><P>CLASS DELIVERY DEFINITION DEFERRED.</P><UL><LI>Forward declares a class named DELIVERY used later to handle double-click events.</LI><LI>This is necessary to register event handlers before the class is fully implemented.</LI></UL><H3 id="toc-hId-1271003901"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>3. Type Declarations</STRONG></H3><P>&nbsp;&nbsp;&nbsp; TYPES: BEGIN OF T_ZDB_EDIT_ALV,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VBELN TYPE ZDB_EDIT_ALV-VBELN,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ERNAM TYPE ZDB_EDIT_ALV-ERNAM,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ERDAT TYPE ZDB_EDIT_ALV-ERDAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VSTEL TYPE ZDB_EDIT_ALV-VSTEL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VKORG TYPE ZDB_EDIT_ALV-VKORG,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CELLTAB TYPE LVC_T_STYL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END OF T_ZDB_EDIT_ALV.</P><UL><LI>Defines a structure T_ZDB_EDIT_ALV to hold header data and editable styles.</LI><LI>CELLTAB: Stores editable style info for ALV cell-level control.</LI></UL><P>Similarly, for item data:</P><P>TYPES: BEGIN OF T_ZDB_EDIT_ALV1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VBELN TYPE ZDB_EDIT_ALV1-VBELN,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POSNR TYPE ZDB_EDIT_ALV1-POSNR,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MATNR TYPE ZDB_EDIT_ALV1-MATNR,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WERKS TYPE ZDB_EDIT_ALV1-WERKS,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CELLTAB TYPE LVC_T_STYL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END OF T_ZDB_EDIT_ALV1.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_0-1749191172558.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270514i3B62808E6E33196E/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_0-1749191172558.png" alt="Naveennani8523_0-1749191172558.png" /></span></P><H3 id="toc-hId-1074490396"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>4. Data Definitions</STRONG></H3><P>DATA: LT_LIKP TYPE TABLE OF T_ZDB_EDIT_ALV,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_LIKP TYPE T_ZDB_EDIT_ALV,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LT_LIPS TYPE TABLE OF T_ZDB_EDIT_ALV1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_LIPS TYPE T_ZDB_EDIT_ALV1,</P><UL><LI>Internal tables and work areas for header (LT_LIKP, LS_LIKP) and item (LT_LIPS, LS_LIPS) records.</LI></UL><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LT_FCAT&nbsp; TYPE LVC_T_FCAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_FCAT&nbsp; TYPE LVC_S_FCAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LT_FCAT1 TYPE LVC_T_FCAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_FCAT1 TYPE LVC_S_FCAT,</P><UL><LI>Field catalog tables for header (LT_FCAT) and item (LT_FCAT1) ALVs.</LI></UL><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_LAYO&nbsp; TYPE LVC_S_LAYO,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_LAYO1 TYPE LVC_S_LAYO,</P><UL><LI>Layout configurations for header and item grids.</LI></UL><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O_CONTAINER1 TYPE REF TO CL_GUI_CUSTOM_CONTAINER,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O_GRID1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TYPE REF TO CL_GUI_ALV_GRID,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O_CONTAINER2 TYPE REF TO CL_GUI_CUSTOM_CONTAINER,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O_GRID2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TYPE REF TO CL_GUI_ALV_GRID,</P><UL><LI>Containers and ALV grid objects for screen 200 (header) and screen 100 (item).</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_1-1749191172560.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270515iF61284AE07665BB2/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_1-1749191172560.png" alt="Naveennani8523_1-1749191172560.png" /></span></P><H2 id="toc-hId-748894172"><STRONG>5. Selection Screen Definition</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_2-1749191172561.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270513i2396566F1D61F909/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_2-1749191172561.png" alt="Naveennani8523_2-1749191172561.png" /></span>&nbsp;</LI><LI><STRONG>Purpose</STRONG>: Creates a selection screen block with delivery number as the input filter.</LI><LI><STRONG>S_VBELN</STRONG>: Allows users to input multiple values or ranges for VBELN.</LI><LI><STRONG>TEXT-000</STRONG>: Refers to a text element (defined in SE32 or SE38) for the frame title.</LI></UL><H2 id="toc-hId-552380667"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>6. Field Catalog for Item ALV</STRONG></H2><UL><LI>Uses VALUE #( ) constructor to populate the field catalog for the item-level ALV (LT_LIPS).</LI><LI>COL_POS: Column order in the ALV.</LI><LI>FIELDNAME: Field to display.</LI><LI>COLTEXT: Header text.</LI><LI>TABNAME: Reference table used for dynamic assignment (not required in OO ALV, but used for clarity here).</LI></UL><H2 id="toc-hId-355867162"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>7. Layout Configuration for Item ALV</STRONG></H2><UL><LI>GRID_TITLE: Title of the ALV.</LI><LI>SEL_MODE = 'A': Allows multiple row selection.</LI><LI>NO_TOOLBAR = 'X': Hides the standard ALV toolbar.</LI><LI>STYLEFNAME = 'CELLTAB': Tells ALV to use the CELLTAB column to control editable styles per cell.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_3-1749191172563.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270521i4DB91C2A1CF5C37B/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_3-1749191172563.png" alt="Naveennani8523_3-1749191172563.png" /></span></P><H2 id="toc-hId-159353657"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>8. Start-of-Selection</STRONG></H2><P>START-OF-SELECTION.&nbsp; CALL SCREEN 200.</P><UL><LI><STRONG>Trigger point of the report</STRONG> after user input.</LI><LI>It navigates to screen <STRONG>200</STRONG>, which displays the <STRONG>header-level ALV</STRONG>.</LI></UL><H2 id="toc-hId--37159848"><STRONG>9. Event Handler Class Definition</STRONG></H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_4-1749191172564.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270519i43AFED4F7130D985/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_4-1749191172564.png" alt="Naveennani8523_4-1749191172564.png" /></span></P><UL><LI>Defines a <STRONG>local class</STRONG> DELIVERY with method GET_DATA.</LI><LI>The method is registered as an event handler for the <STRONG>double-click</STRONG> event of the ALV.</LI></UL><H2 id="toc-hId-113581004"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>10. Class Implementation</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_5-1749191172565.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270520i51CDC5398263A048/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_5-1749191172565.png" alt="Naveennani8523_5-1749191172565.png" /></span>&nbsp;</LI><LI><STRONG>GET_DATA</STRONG> is triggered when the user double-clicks on a row in header ALV.</LI><LI>It reads the delivery number (VBELN) of the clicked row.</LI><LI>Then fetches all matching item-level records from ZDB_EDIT_ALV1 into LT_LIPS.</LI><LI>Opens <STRONG>Screen 100</STRONG>, which shows the item ALV.</LI></UL><H2 id="toc-hId--82932501"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>11. Screen 100 (Item ALV) - OUTPUT Module</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_6-1749191172565.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270525iD5C9E93162F9FC9F/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_6-1749191172565.png" alt="Naveennani8523_6-1749191172565.png" /></span>&nbsp;</LI><LI>SET PF-STATUS 'ZITEMS': Sets the GUI status (button functions) for item screen.</LI><LI>PERFORM CREATE_OBJECT_LIPS: Initializes the ALV Grid for item records.</LI></UL><H2 id="toc-hId--279446006"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>12. Screen 100 - INPUT Module</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_7-1749191172566.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270526i16C6390E23BE8EA2/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_7-1749191172566.png" alt="Naveennani8523_7-1749191172566.png" /></span>&nbsp;</LI><LI>Handles user actions on screen 100:<UL><LI>BACK: Return to header ALV.</LI><LI>CREATE: Add a new item row.</LI><LI>EDIT: Enable selected row for editing.</LI><LI>UPDATE: Update modified item data.</LI><LI>DELETE: Remove selected rows.</LI><LI>SAVE: Insert/update item data into DB.</LI></UL></LI></UL><OL><LI>FORM CREATE_OBJECT_LIPS – Initializes ALV on Screen 100 (Item).</LI><LI>MODULE STATUS_0200 OUTPUT – Prepares header ALV on Screen 200.</LI><LI>MODULE USER_COMMAND_0200 INPUT – Handles toolbar actions for header ALV.</LI><LI>Then we’ll go deeper into the CRUD FORMs (CREATE/EDIT/UPDATE/DELETE/SAVE) for both header and item ALVs.</LI><LI>FORM CREATE_OBJECT_LIPS<STRONG> – Create ALV Grid for Items</STRONG></LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_8-1749191172568.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270527i734C2BC0C54B2623/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_8-1749191172568.png" alt="Naveennani8523_8-1749191172568.png" /></span></P><H3 id="toc-hId--769362518"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span></H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_9-1749191172569.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270531i4CB17536C154A57F/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_9-1749191172569.png" alt="Naveennani8523_9-1749191172569.png" /></span></P><H3 id="toc-hId--965876023">Explanation:</H3><UL><LI><STRONG>CLEAR O_CONTAINER2</STRONG>: Reset reference before ALV creation (safety check).</LI><LI><STRONG>CREATE OBJECT O_CONTAINER2</STRONG>: Creates a custom container placed on the screen (SCREEN 100) using element CONTAINER2.</LI><LI><STRONG>CREATE OBJECT O_GRID2</STRONG>: Binds an ALV Grid (CL_GUI_ALV_GRID) to the container.</LI><LI><STRONG>SET_TABLE_FOR_FIRST_DISPLAY</STRONG>:<UL><LI>IS_LAYOUT = LS_LAYO1: Applies previously configured layout for item ALV.</LI><LI>IT_OUTTAB = LT_LIPS: Data source for the ALV.</LI><LI>IT_FIELDCATALOG = LT_FCAT1: Column settings for the ALV.</LI></UL></LI></UL><H2 id="toc-hId--868986521"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>13. </STRONG>MODULE STATUS_0200 OUTPUT<STRONG> – Setup Header Screen (Screen 200)</STRONG></H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_10-1749191172570.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270532i83CF7510823FDB5B/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_10-1749191172570.png" alt="Naveennani8523_10-1749191172570.png" /></span></P><H3 id="toc-hId--1358903033">Explanation:</H3><UL><LI>SET PF-STATUS 'ZHEADER': Sets GUI status for header toolbar (buttons: CREATE, EDIT, SAVE, etc.).</LI><LI>The SELECT pulls header records from ZDB_EDIT_ALV based on delivery numbers entered on the selection screen.</LI></UL><H3 id="toc-hId--1555416538">ALV Grid Initialization:</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_11-1749191172571.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270533i265DBA4C13AC9AB3/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_11-1749191172571.png" alt="Naveennani8523_11-1749191172571.png" /></span></P><P>Creates the custom container and grid for header-level display.</P><H3 id="toc-hId--1751930043">Field Catalog (LT_FCAT):</H3><P>Each field is appended individually to LT_FCAT with attributes:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_12-1749191172572.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270538iE759BD09E2E00333/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_12-1749191172572.png" alt="Naveennani8523_12-1749191172572.png" /></span></P><H3 id="toc-hId--1948443548">&nbsp;Layout for Header ALV:</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_13-1749191172572.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270537iD5CA4EA8002C1EF9/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_13-1749191172572.png" alt="Naveennani8523_13-1749191172572.png" /></span></P><P>&nbsp;Final ALV Setup:</P><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_14-1749191172573.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270539iB7074AD502A45837/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_14-1749191172573.png" alt="Naveennani8523_14-1749191172573.png" /></span>&nbsp;</LI><LI>Initializes header ALV with all settings and data.</LI></UL><H3 id="toc-hId--1976773362">Event Handler Registration:</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_15-1749191172574.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270543iE0337B8F0B95246F/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_15-1749191172574.png" alt="Naveennani8523_15-1749191172574.png" /></span></P><P>&nbsp;Double-click on any row in header ALV triggers GET_DATA, which fetches corresponding items.</P><H2 id="toc-hId--1879883860"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>14. </STRONG>MODULE USER_COMMAND_0200 INPUT<STRONG> – Header Screen Toolbar Actions</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_16-1749191172575.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270544i2F64A0BDCBC1BBD4/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_16-1749191172575.png" alt="Naveennani8523_16-1749191172575.png" /></span>&nbsp;</LI><LI>Executes the relevant FORM based on user action on toolbar buttons:<UL><LI>CREATE: Adds a new editable row.</LI><LI>EDIT: Enables selected row for editing.</LI><LI>SAVE: Inserts or updates data in DB.</LI><LI>DELETE: Removes selected rows from ALV and DB.</LI><LI>UPDATE: Commits modified data to DB.</LI></UL></LI></UL><H2 id="toc-hId--2076397365"><STRONG>15. </STRONG>FORM CHANGE_MODE<STRONG> – Enable Edit Mode for Selected Header Row</STRONG></H2><UL><LI><STRONG>Purpose</STRONG>: Only the selected row becomes editable. All others stay read-only.</LI><LI>LVC_T_ROID, LVC_S_STYL: Types for editable styles.</LI><LI>CELLTAB is used for cell-level control.</LI><LI>Gets the row(s) selected in the <STRONG>header ALV</STRONG> using LVC_ROWMARK.</LI></UL><P>&nbsp; Loop over each header entry to determine which row to enable. &nbsp;</P><UL><LI>Compares the current loop index with selected rows.</LI><LI>If it’s selected, enable its editable fields.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_17-1749191172578.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270545i8D5AB73879134397/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_17-1749191172578.png" alt="Naveennani8523_17-1749191172578.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_18-1749191172580.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270551iBF3BED421B2410A7/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_18-1749191172580.png" alt="Naveennani8523_18-1749191172580.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_19-1749191172582.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270550iFD30EDFC3278D02D/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_19-1749191172582.png" alt="Naveennani8523_19-1749191172582.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_20-1749191172583.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270549i2A6012EFF7A85B47/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_20-1749191172583.png" alt="Naveennani8523_20-1749191172583.png" /></span></P><H3 id="toc-hId-1728653419"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> If Selected Row → Enable ditable Fields</H3><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-FIELDNAME = 'VBELN'.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.</P><UL><LI>VBELN is a primary key → disabled.</LI><LI>Similarly disables ERNAM.</LI></UL><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-FIELDNAME = 'ERDAT'.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.</P><UL><LI>Enables only non-primary key fields for editing: ERDAT, VSTEL, VKORG.</LI></UL><H3 id="toc-hId-1532139914"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Assign Cell Styles to Entry</H3><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR: LS_LIKP-CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIKP-CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR: LT_STYLEROW.</P><UL><LI>Applies the style to the current line.</LI></UL><H3 id="toc-hId-1335626409"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Else – Row not selected → Make it fully non-editable</H3><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ELSE.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB.</P><H3 id="toc-hId-1139112904"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Toggle Grid Ready for Input</H3><P>&nbsp; IF O_GRID1-&gt;IS_READY_FOR_INPUT( ) EQ 0.&nbsp;&nbsp;&nbsp; CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1.&nbsp; ELSE.&nbsp;&nbsp;&nbsp; CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0.&nbsp; ENDIF.</P><UL><LI>Activates input mode if not already.</LI></UL><P>&nbsp; O_GRID1-&gt;REFRESH_TABLE_DISPLAY( ).ENDFORM.</P><UL><LI>Refreshes the ALV to reflect the updated editable state.</LI><LI>&nbsp;</LI></UL><H2 id="toc-hId-1236002406"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>16. </STRONG>FORM CREATE_HEADER_DATA<STRONG> – Add New Editable Header Row</STRONG></H2><P>FORM CREATE_HEADER_DATA .&nbsp; DATA: LS_NEW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TYPE T_ZDB_EDIT_ALV,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW TYPE LVC_S_STYL.</P><UL><LI>Prepares a new structure and editable field style list.</LI></UL><H3 id="toc-hId-746085894"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Set Editable Fields</H3><P>&nbsp; LS_STYLEROW-FIELDNAME = 'VBELN'.&nbsp; LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED.&nbsp; APPEND LS_STYLEROW TO LT_STYLEROW.</P><UL><LI>All fields are enabled since it’s a <STRONG>new row</STRONG>. Even primary keys like VBELN, ERNAM.</LI><LI>Repeats for: ERNAM, ERDAT, VSTEL, VKORG.</LI></UL><H3 id="toc-hId-549572389"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Assign Styles and Add New Entry</H3><P>&nbsp; LS_NEW-CELLTAB = LT_STYLEROW.&nbsp; APPEND LS_NEW TO LT_LIKP.</P><UL><LI>Assigns the editable CELLTAB and appends the new row to the internal table.</LI></UL><P>&nbsp; CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1.&nbsp; CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY.ENDFORM.</P><UL><LI>Turns on editable mode and refreshes ALV.</LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_21-1749191172584.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270556i7AB39BA0215081E0/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_21-1749191172584.png" alt="Naveennani8523_21-1749191172584.png" /></span></LI></UL><H2 id="toc-hId-814645582"><STRONG>17. </STRONG>FORM DELETE_HEADER_DATA<STRONG> – Delete Selected Header Rows</STRONG></H2><P>FORM DELETE_HEADER_DATA .&nbsp; DATA: LT_ROWS TYPE LVC_T_ROW,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_ROW&nbsp; TYPE LVC_S_ROW,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LV_IDX&nbsp; TYPE SY-TABIX.</P><UL><LI><STRONG>LT_ROWS</STRONG>: Holds the list of selected row indexes.</LI><LI><STRONG>LS_ROW</STRONG>: Work area for current row index.</LI><LI><STRONG>LV_IDX</STRONG>: Integer used to track which row index is being processed.</LI></UL><H3 id="toc-hId-324729070"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Get Selected Rows</H3><P>&nbsp; CALL METHOD O_GRID1-&gt;GET_SELECTED_ROWS&nbsp;&nbsp;&nbsp; IMPORTING ET_INDEX_ROWS = LT_ROWS.</P><UL><LI>Fetches the selected row indexes in the header ALV grid.</LI></UL><H3 id="toc-hId-128215565"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop and Delete from DB &amp; Internal Table</H3><P>&nbsp; LOOP AT LT_ROWS INTO LS_ROW.&nbsp;&nbsp;&nbsp; LV_IDX = LS_ROW-INDEX.&nbsp;&nbsp;&nbsp;&nbsp; READ TABLE LT_LIKP INDEX LV_IDX INTO LS_LIKP.&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DELETE FROM ZDB_EDIT_ALV WHERE VBELN = LS_LIKP-VBELN.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DELETE LT_LIKP INDEX LV_IDX.&nbsp;&nbsp;&nbsp; ENDIF.&nbsp; ENDLOOP.</P><UL><LI>For each selected row:<UL><LI>Reads that entry from LT_LIKP.</LI><LI>Deletes corresponding record from DB table ZDB_EDIT_ALV.</LI><LI>Deletes it from internal table LT_LIKP.</LI></UL></LI></UL><H3 id="toc-hId--68297940"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Refresh ALV &amp; Commit</H3><P>&nbsp; CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY.&nbsp; COMMIT WORK.&nbsp; MESSAGE 'Selected header(s) deleted' TYPE 'S'.ENDFORM.</P><UL><LI>Refreshes the ALV display.</LI><LI>Saves DB changes using COMMIT WORK.</LI><LI>Displays success message.</LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_22-1749191172585.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270555i52DD83DEFB59E248/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_22-1749191172585.png" alt="Naveennani8523_22-1749191172585.png" /></span></LI></UL><H2 id="toc-hId-28591562"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>18. </STRONG>FORM SAVE_HEADER_DATA<STRONG> – Insert or Update Header Records</STRONG></H2><P>FORM SAVE_HEADER_DATA .</P><H3 id="toc-hId--461324950"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Flat Structure Definition</H3><P>TYPES: BEGIN OF TY_ZDB_EDIT_ALV_FLAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VBELN TYPE ZDB_EDIT_ALV-VBELN,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ERNAM TYPE ZDB_EDIT_ALV-ERNAM,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ERDAT TYPE ZDB_EDIT_ALV-ERDAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VSTEL TYPE ZDB_EDIT_ALV-VSTEL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VKORG TYPE ZDB_EDIT_ALV-VKORG,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END OF TY_ZDB_EDIT_ALV_FLAT.&nbsp;DATA: LS_DB_ALV_FLAT TYPE TY_ZDB_EDIT_ALV_FLAT.</P><UL><LI>This structure <STRONG>excludes CELLTAB</STRONG> and is used to write data into the DB.</LI><LI>&nbsp;</LI></UL><H3 id="toc-hId--657838455"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Ensure User Changes Are Captured</H3><P>&nbsp; CALL METHOD O_GRID1-&gt;CHECK_CHANGED_DATA.</P><UL><LI>Updates the internal table (LT_LIKP) with user input from the ALV grid.</LI></UL><H3 id="toc-hId--854351960"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop Through Header Table and Save to DB</H3><P>&nbsp;&nbsp; LOOP AT LT_LIKP INTO LS_LIKP.&nbsp;&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-VBELN = LS_LIKP-VBELN.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-ERNAM = LS_LIKP-ERNAM.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-ERDAT = LS_LIKP-ERDAT.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-VSTEL = LS_LIKP-VSTEL.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-VKORG = LS_LIKP-VKORG.</P><UL><LI>Copies the values to a flat version to avoid CELLTAB structure issues.</LI></UL><H3 id="toc-hId--1050865465"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Insert or Update Logic</H3><P>&nbsp;&nbsp;&nbsp; SELECT SINGLE VBELN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(LV_VBELN)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM ZDB_EDIT_ALV&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM.&nbsp;&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UPDATE ZDB_EDIT_ALV SET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT,&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM.&nbsp;&nbsp;&nbsp; ELSE.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT.&nbsp;&nbsp;&nbsp; ENDIF.&nbsp;&nbsp; ENDLOOP.</P><UL><LI>If record exists (same VBELN &amp; ERNAM) → UPDATE.</LI><LI>Else → INSERT as new record.</LI></UL><P>&nbsp; COMMIT WORK.&nbsp; MESSAGE 'Header data saved successfully' TYPE 'S'.ENDFORM.</P><UL><LI>Final commit and success message.</LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_23-1749191172586.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270557iFF0F6628B23C836F/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_23-1749191172586.png" alt="Naveennani8523_23-1749191172586.png" /></span></LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_24-1749191172587.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270564i48AA7AE99A09641A/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_24-1749191172587.png" alt="Naveennani8523_24-1749191172587.png" /></span></LI></UL><H2 id="toc-hId--953975963"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>19. </STRONG>FORM UPDATE_HEADER_DATA<STRONG> – Update Header Records</STRONG></H2><P>FORM UPDATE_HEADER_DATA .&nbsp; CALL METHOD O_GRID1-&gt;CHECK_CHANGED_DATA.</P><UL><LI>Reads current ALV data into LT_LIKP.</LI></UL><H3 id="toc-hId--1275708784"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop and Upsert to DB</H3><P>&nbsp;LOOP AT LT_LIKP INTO LS_LIKP.&nbsp;&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-VBELN = LS_LIKP-VBELN.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-ERNAM = LS_LIKP-ERNAM.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-ERDAT = LS_LIKP-ERDAT.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-VSTEL = LS_LIKP-VSTEL.&nbsp;&nbsp;&nbsp; LS_DB_ALV_FLAT-VKORG = LS_LIKP-VKORG.</P><UL><LI>Maps data into a flat structure.</LI></UL><P>&nbsp; &nbsp;SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(LV_VBELN)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM ZDB_EDIT_ALV&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM.&nbsp;&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UPDATE ZDB_EDIT_ALV SET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM.&nbsp;&nbsp;&nbsp; ELSE.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT.&nbsp;&nbsp;&nbsp; ENDIF.&nbsp;&nbsp; ENDLOOP.</P><UL><LI>Same insert/update logic as SAVE</LI></UL><P>&nbsp; COMMIT WORK.&nbsp; MESSAGE 'Header data Updated successfully' TYPE 'S'.ENDFORM.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_25-1749191172589.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270558iC67E9D92035DC1A8/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_25-1749191172589.png" alt="Naveennani8523_25-1749191172589.png" /></span></P><P>&nbsp;</P><P><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> That completes the full documentation of <STRONG>header-level editable ALV with CRUD</STRONG>.</P><P>Next, I’ll begin the <STRONG>item-level ALV explanation</STRONG> starting with:</P><OL><LI>FORM CHANGE_ITEMS_MODE</LI><LI>FORM CREATE_ITEMS_DATA</LI><LI>FORM DELETE_ITEMS_DATA</LI><LI>FORM SAVE_ITEMS_DATA</LI><LI>FORM UPDATE_ITEMS_DATA</LI></OL><H2 id="toc-hId--1178819282"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>20. </STRONG>FORM CHANGE_ITEMS_MODE<STRONG> – Make Only Selected Item Row Editable</STRONG></H2><P>FORM CHANGE_ITEMS_MODE .&nbsp; DATA: LT_INDEX_ROWS TYPE LVC_T_ROW,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LT_ROW_NO&nbsp;&nbsp;&nbsp;&nbsp; TYPE LVC_T_ROID,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_ROW_NO&nbsp;&nbsp;&nbsp;&nbsp; TYPE LVC_S_ROID,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW&nbsp;&nbsp; TYPE LVC_S_STYL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LT_STYLEROW&nbsp;&nbsp; TYPE TABLE OF LVC_S_STYL.</P><UL><LI>Similar to header edit logic.</LI><LI>Used to control which <STRONG>single row</STRONG> in the item ALV becomes editable.</LI></UL><P>&nbsp; CALL METHOD O_GRID2-&gt;GET_SELECTED_ROWS&nbsp;&nbsp;&nbsp; IMPORTING ET_ROW_NO = LT_ROW_NO.</P><UL><LI>Retrieves the selected item rows using LVC_ROWMARK.</LI></UL><H3 id="toc-hId--1668735794"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop Over All Rows and Toggle Editable Mode</H3><P>&nbsp; IF NOT LT_ROW_NO IS INITIAL.&nbsp;&nbsp;&nbsp; LOOP AT LT_LIPS INTO LS_LIPS.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; READ TABLE LT_ROW_NO INTO LS_ROW_NO WITH KEY ROW_ID = SY-TABIX.</P><UL><LI>For each item row in LT_LIPS, check if it’s selected.</LI></UL><H3 id="toc-hId--1865249299"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> If Selected: Enable Editable Fields</H3><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-STYLE&nbsp;&nbsp;&nbsp;&nbsp; = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-FIELDNAME = 'VBELN'.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-FIELDNAME = 'POSNR'.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-STYLE&nbsp;&nbsp;&nbsp;&nbsp; = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-FIELDNAME = 'MATNR'.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-FIELDNAME = 'WERKS'.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.</P><UL><LI>VBELN and POSNR are primary keys → disabled.</LI><LI>Only MATNR, WERKS are editable.</LI></UL><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR: LS_LIPS-CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR: LT_STYLEROW.</P><UL><LI>Applies the cell-style configuration to the current row.</LI></UL><H3 id="toc-hId--2061762804"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Else: Disable All Fields for Non-Selected Rows</H3><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ELSE.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LOOP AT FIELDS: 'VBELN', 'POSNR', 'MATNR', 'WERKS'.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-FIELDNAME = FIELD.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ENDLOOP.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR: LS_LIPS-CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR: LT_STYLEROW.</P><H3 id="toc-hId-2036690987"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Toggle Edit Mode and Refresh ALV</H3><P>&nbsp; IF O_GRID2-&gt;IS_READY_FOR_INPUT( ) EQ 0.&nbsp;&nbsp;&nbsp; CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1.&nbsp; ELSE.&nbsp;&nbsp;&nbsp; CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0.&nbsp; ENDIF.&nbsp;&nbsp; O_GRID2-&gt;REFRESH_TABLE_DISPLAY( ).ENDFORM.</P><H2 id="toc-hId-2133580489"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>21. </STRONG>FORM CREATE_ITEMS_DATA<STRONG> – Add New Editable Row in Item ALV</STRONG></H2><P>FORM CREATE_ITEMS_DATA .&nbsp; DATA: LS_NEW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TYPE T_ZDB_EDIT_ALV1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_STYLEROW TYPE LVC_S_STYL.&nbsp;&nbsp; CLEAR: LS_NEW, LT_STYLEROW.</P><UL><LI>Creates a blank work area and editable style table.</LI></UL><H3 id="toc-hId-1643663977"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Enable All Fields (for Create)</H3><P>&nbsp; LS_STYLEROW-FIELDNAME = 'VBELN'.&nbsp; LS_STYLEROW-STYLE&nbsp;&nbsp;&nbsp;&nbsp; = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED.&nbsp; APPEND LS_STYLEROW TO LT_STYLEROW.&nbsp;&nbsp; ... (Repeat for POSNR, MATNR, WERKS)</P><UL><LI>All fields are enabled so user can create new record from scratch.</LI></UL><P>&nbsp; LS_NEW-CELLTAB = LT_STYLEROW.&nbsp; APPEND LS_NEW TO LT_LIPS.&nbsp;&nbsp; CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1.&nbsp; CALL METHOD O_GRID2-&gt;REFRESH_TABLE_DISPLAY.ENDFORM.</P><UL><LI>Appends the new row to ALV and switches to input mode.</LI></UL><H2 id="toc-hId-1740553479"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>22. </STRONG>FORM DELETE_ITEMS_DATA<STRONG> – Delete Selected Item Rows</STRONG></H2><P>FORM DELETE_ITEMS_DATA .&nbsp; DATA: LT_ROWS TYPE LVC_T_ROW,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_ROW&nbsp; TYPE LVC_S_ROW,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LV_IDX&nbsp; TYPE SY-TABIX.&nbsp;&nbsp; CALL METHOD O_GRID2-&gt;GET_SELECTED_ROWS IMPORTING ET_INDEX_ROWS = LT_ROWS.</P><UL><LI>Gets the selected item row indexes from ALV.</LI></UL><P>&nbsp; LOOP AT LT_ROWS INTO LS_ROW.&nbsp;&nbsp;&nbsp; LV_IDX = LS_ROW-INDEX.&nbsp;&nbsp;&nbsp; READ TABLE LT_LIPS INDEX LV_IDX INTO LS_LIPS.&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DELETE FROM ZDB_EDIT_ALV1 WHERE VBELN = LS_LIPS-VBELN.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DELETE LT_LIPS INDEX LV_IDX.&nbsp;&nbsp;&nbsp; ENDIF.&nbsp; ENDLOOP.&nbsp;&nbsp; CALL METHOD O_GRID2-&gt;REFRESH_TABLE_DISPLAY.&nbsp; COMMIT WORK.&nbsp; MESSAGE 'Selected header(s) deleted' TYPE 'S'.ENDFORM.</P><UL><LI>Deletes item records from both DB and internal table.</LI></UL><H2 id="toc-hId-1544039974"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>23. </STRONG>FORM SAVE_ITEMS_DATA<STRONG> – Insert or Update Item Rows</STRONG></H2><P>FORM SAVE_ITEMS_DATA .&nbsp; DATA: LS_DB_ALV1&nbsp; TYPE TY_ZDB_EDIT_ALV1_FLAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_DB_FULL TYPE ZDB_EDIT_ALV1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LV_VBELN&nbsp;&nbsp; TYPE ZDB_EDIT_ALV1-VBELN.&nbsp;&nbsp; CALL METHOD O_GRID2-&gt;CHECK_CHANGED_DATA.</P><UL><LI>Converts ALV changes to internal table.</LI><LI>Flat structure is used to exclude CELLTAB.</LI></UL><H3 id="toc-hId-1222307153"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop Through Item Table</H3><P>&nbsp; LOOP AT LT_LIPS INTO LS_LIPS.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-VBELN = LS_LIPS-VBELN.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-POSNR = LS_LIPS-POSNR.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-MATNR = LS_LIPS-MATNR.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-WERKS = LS_LIPS-WERKS.</P><UL><LI>Transfer values from ALV row to flat structure.</LI></UL><H3 id="toc-hId-1025793648"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> DB Insert/Update Logic</H3><P>&nbsp;&nbsp;&nbsp; SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_VBELN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM ZDB_EDIT_ALV1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR.&nbsp;&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UPDATE ZDB_EDIT_ALV1 SET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR.&nbsp;&nbsp;&nbsp; ELSE.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR LS_DB_FULL.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL.&nbsp;&nbsp;&nbsp; ENDIF.&nbsp; ENDLOOP. &nbsp; COMMIT WORK.&nbsp; MESSAGE 'Item data saved successfully' TYPE 'S'.ENDFORM.</P><H2 id="toc-hId-1122683150"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>24. </STRONG>FORM UPDATE_ITEMS_DATA<STRONG> – Update Existing Item Records</STRONG></H2><P>FORM UPDATE_ITEMS_DATA .&nbsp; DATA: LS_DB_ALV1&nbsp; TYPE TY_ZDB_EDIT_ALV1_FLAT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LS_DB_FULL TYPE ZDB_EDIT_ALV1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LV_VBELN&nbsp;&nbsp; TYPE ZDB_EDIT_ALV1-VBELN.&nbsp;&nbsp; CALL METHOD O_GRID2-&gt;CHECK_CHANGED_DATA.</P><UL><LI>Same structure and update logic as SAVE.</LI></UL><P>&nbsp; LOOP AT LT_LIPS INTO LS_LIPS.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-VBELN = LS_LIPS-VBELN.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-POSNR = LS_LIPS-POSNR.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-MATNR = LS_LIPS-MATNR.&nbsp;&nbsp;&nbsp; LS_DB_ALV1-WERKS = LS_LIPS-WERKS. &nbsp;&nbsp;&nbsp; SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(S_VBELN)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM ZDB_EDIT_ALV1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR.&nbsp;&nbsp;&nbsp;&nbsp; IF SY-SUBRC = 0.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UPDATE ZDB_EDIT_ALV1 SET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR.&nbsp;&nbsp;&nbsp; ELSE.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CLEAR LS_DB_FULL.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL.&nbsp;&nbsp;&nbsp; ENDIF.&nbsp; ENDLOOP.&nbsp;&nbsp; COMMIT WORK.&nbsp; MESSAGE 'Item data Updated successfully' TYPE 'S'.ENDFORM.<STRONG>Output:</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_26-1749191172589.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270560iBEE936E82F368032/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_26-1749191172589.png" alt="Naveennani8523_26-1749191172589.png" /></span></P><P>&nbsp;Header Output</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_27-1749191172591.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270566i3CE4A6D89D67F78B/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_27-1749191172591.png" alt="Naveennani8523_27-1749191172591.png" /></span></P><P>&nbsp;When I was click on edit button</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_28-1749191172595.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270567i057B849479B6AC8F/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_28-1749191172595.png" alt="Naveennani8523_28-1749191172595.png" /></span></P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_29-1749191172596.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270565iDC47F60D1A00314B/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_29-1749191172596.png" alt="Naveennani8523_29-1749191172596.png" /></span></P><P>When I was click on create button</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_30-1749191172598.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270571iEE61E24AE577EB58/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_30-1749191172598.png" alt="Naveennani8523_30-1749191172598.png" /></span></P><P>When I was create a new row delete button</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_31-1749191172599.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270572iEAE815660983589B/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_31-1749191172599.png" alt="Naveennani8523_31-1749191172599.png" /></span></P><P>When I was click on create buttom multiple append rows also created in both header and item also</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_32-1749191172600.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270573iFA3C2CDDC454A5D3/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_32-1749191172600.png" alt="Naveennani8523_32-1749191172600.png" /></span></P><P>If I was save on empty row Its shows as</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_33-1749191172601.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270579iE50DABA8FE3E4BA6/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_33-1749191172601.png" alt="Naveennani8523_33-1749191172601.png" /></span></P><P>If was double click on empty on no items was displayed and Header empty row it will not created on items details</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_34-1749191172601.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270578i5D35C2D7AA981E94/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_34-1749191172601.png" alt="Naveennani8523_34-1749191172601.png" /></span></P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_35-1749191172602.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270580i95316A0929BE635C/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_35-1749191172602.png" alt="Naveennani8523_35-1749191172602.png" /></span></P><P>&nbsp;</P><P>Same actions performs in CURD operations in item level also:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_36-1749191172603.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270583i87EFC691220BBDC0/image-size/medium?v=v2&amp;px=400" role="button" title="Naveennani8523_36-1749191172603.png" alt="Naveennani8523_36-1749191172603.png" /></span></P><P>&nbsp;</P><P><SPAN><STRONG>Program :</STRONG></SPAN></P><pre class="lia-code-sample language-abap"><code>REPORT ZEDITABLE_ALV_INT. ************************************************************************ * Program Name : * Description : Editable ALV using CL_GUI_ALV_GRID with row-based edit * control using LVC_ROWMARK. Only selected row becomes * editable, primary keys remain non-editable and to perfrom a crud operations. * Created by : &lt;NRAJU&gt; ************************************************************************* *---------------------------------------------------------------------* * Table Declarations *---------------------------------------------------------------------* TABLES:ZDB_EDIT_ALV,ZDB_EDIT_ALV1. CLASS DELIVERY DEFINITION DEFERRED. *---------------------------------------------------------------------* * Type Declarations *---------------------------------------------------------------------* TYPES: BEGIN OF T_ZDB_EDIT_ALV, VBELN TYPE ZDB_EDIT_ALV-VBELN, "Delivery Number ERNAM TYPE ZDB_EDIT_ALV-ERNAM, "Name of Person who Created the Object ERDAT TYPE ZDB_EDIT_ALV-ERDAT, "Date on Which Record Was Created VSTEL TYPE ZDB_EDIT_ALV-VSTEL, "Shipping Point/Receiving Point VKORG TYPE ZDB_EDIT_ALV-VKORG, "Sales Organization CELLTAB TYPE LVC_T_STYL, "Editable style table END OF T_ZDB_EDIT_ALV. TYPES: BEGIN OF T_ZDB_EDIT_ALV1, VBELN TYPE ZDB_EDIT_ALV1-VBELN, "Delivery Number POSNR TYPE ZDB_EDIT_ALV1-POSNR, "Sales Document Item ERNAM TYPE ZDB_EDIT_ALV1-ERNAM, MATNR TYPE ZDB_EDIT_ALV1-MATNR, "Material Number WERKS TYPE ZDB_EDIT_ALV1-WERKS, "Plant CELLTAB TYPE LVC_T_STYL, "Editable style table END OF T_ZDB_EDIT_ALV1. DATA:LT_LIKP TYPE TABLE OF T_ZDB_EDIT_ALV, "Internal table for header LS_LIKP TYPE T_ZDB_EDIT_ALV, "workarea for header LT_LIPS TYPE TABLE OF T_ZDB_EDIT_ALV1, "Internal table for Item LS_LIPS TYPE T_ZDB_EDIT_ALV1, "Workarea for item LT_FCAT TYPE LVC_T_FCAT, "Filedcat LS_FCAT TYPE LVC_S_FCAT, LT_FCAT1 TYPE LVC_T_FCAT, "filedcatlog LS_FCAT1 TYPE LVC_S_FCAT, LS_LAYO TYPE LVC_S_LAYO, "Layout LS_LAYO1 TYPE LVC_S_LAYO, O_CONTAINER1 TYPE REF TO CL_GUI_CUSTOM_CONTAINER, "Container for Header O_GRID1 TYPE REF TO CL_GUI_ALV_GRID, "Grid for Header O_CONTAINER2 TYPE REF TO CL_GUI_CUSTOM_CONTAINER, "Container for item O_GRID2 TYPE REF TO CL_GUI_ALV_GRID. "Grid for It *---------------------------------------------------------------------* * Selection Screen *---------------------------------------------------------------------* SELECTION-SCREEN BEGIN OF BLOCK B1 WITH FRAME TITLE TEXT-000. SELECT-OPTIONS:S_VBELN FOR ZDB_EDIT_ALV-VBELN. SELECTION-SCREEN END OF BLOCK B1. *************fieldcatalog creation creation for item LT_FCAT1 = VALUE #( ( COL_POS = 1 FIELDNAME = 'VBELN' COLTEXT = 'Delivery Number' ) ( COL_POS = 2 FIELDNAME = 'POSNR' COLTEXT = 'Item Number' ) ( COL_POS = 3 FIELDNAME = 'ERNAM' COLTEXT = 'NAME' ) ( COL_POS = 4 FIELDNAME = 'MATNR' COLTEXT = 'Material Number' ) ( COL_POS = 5 FIELDNAME = 'WERKS' COLTEXT = 'Plant' ) ). *************Layout creation for item LS_LAYO1-GRID_TITLE = 'Custom Table for Items'. LS_LAYO1-SEL_MODE = 'A'. LS_LAYO1-NO_TOOLBAR = 'X'. LS_LAYO1-STYLEFNAME = 'CELLTAB'. "*************fieldcatalog creation creation LS_FCAT-ROW_POS = 1. LS_FCAT-COL_POS = 1. LS_FCAT-FIELDNAME = 'VBELN'. LS_FCAT-COLTEXT = 'Delivery Number'. LS_FCAT-OUTPUTLEN = 20. APPEND LS_FCAT TO LT_FCAT. CLEAR LS_FCAT. LS_FCAT-ROW_POS = 1. LS_FCAT-COL_POS = 1. LS_FCAT-FIELDNAME = 'ERNAM'. LS_FCAT-COLTEXT = 'Name'. LS_FCAT-OUTPUTLEN = 20. APPEND LS_FCAT TO LT_FCAT. CLEAR LS_FCAT. LS_FCAT-ROW_POS = 1. LS_FCAT-COL_POS = 1. LS_FCAT-FIELDNAME = 'ERDAT'. LS_FCAT-COLTEXT = 'Date'. LS_FCAT-OUTPUTLEN = 20. APPEND LS_FCAT TO LT_FCAT. CLEAR LS_FCAT. LS_FCAT-ROW_POS = 1. LS_FCAT-COL_POS = 1. LS_FCAT-FIELDNAME = 'VSTEL'. LS_FCAT-COLTEXT = 'SALES'. LS_FCAT-OUTPUTLEN = 20. APPEND LS_FCAT TO LT_FCAT. CLEAR LS_FCAT. LS_FCAT-ROW_POS = 1. LS_FCAT-COL_POS = 1. LS_FCAT-FIELDNAME = 'VKORG'. LS_FCAT-COLTEXT = 'Delivery Number'. LS_FCAT-OUTPUTLEN = 20. APPEND LS_FCAT TO LT_FCAT. CLEAR LS_FCAT. ***********layout of fieldcat LS_LAYO-GRID_TITLE = 'Custom Table for Header'. LS_LAYO-SEL_MODE = 'A'. LS_LAYO-NO_TOOLBAR = 'X'. LS_LAYO-STYLEFNAME = 'CELLTAB'. START-OF-SELECTION. "start-of-selection CALL SCREEN 200. "Screen for Header CLASS Delivery DEFINITION. PUBLIC SECTION. METHODS: GET_DATA FOR EVENT DOUBLE_CLICK OF CL_GUI_ALV_GRID IMPORTING E_ROW. ENDCLASS. *&amp;---------------------------------------------------------------------* *&amp; Class (Implementation) Delivery *&amp;---------------------------------------------------------------------* * Text *----------------------------------------------------------------------* CLASS DELIVERY IMPLEMENTATION. METHOD: GET_DATA. READ TABLE LT_LIKP INTO LS_LIKP INDEX E_ROW-INDEX. SELECT VBELN POSNR ERNAM MATNR WERKS FROM ZDB_EDIT_ALV1 INTO CORRESPONDING FIELDS OF TABLE LT_LIPS WHERE VBELN = LS_LIKP-VBELN and ernam = ls_likp-ernam. ** Check if items exist * IF lt_lips IS INITIAL. * MESSAGE 'No items exist for this header.' TYPE 'I'. * RETURN. * ENDIF. CALL SCREEN 100. * " Refresh ALV to reflect changes * CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY. ENDMETHOD. ENDCLASS. "Delivery *&amp;---------------------------------------------------------------------* *&amp; Module STATUS_0100 OUTPUT *&amp;---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE STATUS_0100 OUTPUT. SET PF-STATUS 'ZITEMS'. "Creating buttons for items PERFORM CREATE_OBJECT_LIPS. "perform for create item ENDMODULE. *&amp;---------------------------------------------------------------------* *&amp; Module USER_COMMAND_0100 INPUT *&amp;---------------------------------------------------------------------* * text *----------------------------------------------------------------------* MODULE USER_COMMAND_0100 INPUT. CASE SY-UCOMM. WHEN 'BACK'. LEAVE TO SCREEN 200. WHEN 'CREATE'. "Createing new record for items PERFORM CREATE_ITEMS_DATA. WHEN 'EDIT'. "Editable alv for items PERFORM CHANGE_ITEMS_MODE. WHEN 'UPDATE'. "Updateing the records for items PERFORM UPDATE_ITEMS_DATA. WHEN 'DELETE'. "Deleting the records for item tables PERFORM DELETE_ITEMS_DATA. WHEN 'SAVE'. "Saveing the recording from db table in item records PERFORM SAVE_ITEMS_DATA. ENDCASE. ENDMODULE. *&amp;---------------------------------------------------------------------* *&amp; Form CREATE_OBJECT_LIPS FORM CREATE_OBJECT_LIPS . CLEAR O_CONTAINER2. IF O_CONTAINER2 IS INITIAL AND O_GRID2 IS INITIAL. CREATE OBJECT O_CONTAINER2 EXPORTING CONTAINER_NAME = 'CONTAINER2' EXCEPTIONS CNTL_ERROR = 1 CNTL_SYSTEM_ERROR = 2 CREATE_ERROR = 3 LIFETIME_ERROR = 4 LIFETIME_DYNPRO_DYNPRO_LINK = 5 OTHERS = 6 . CREATE OBJECT O_GRID2 EXPORTING I_PARENT = O_CONTAINER2 EXCEPTIONS ERROR_CNTL_CREATE = 1 ERROR_CNTL_INIT = 2 ERROR_CNTL_LINK = 3 ERROR_DP_CREATE = 4 OTHERS = 5 . ENDIF. CALL METHOD O_GRID2-&gt;SET_TABLE_FOR_FIRST_DISPLAY EXPORTING IS_LAYOUT = LS_LAYO1 CHANGING IT_OUTTAB = LT_LIPS IT_FIELDCATALOG = LT_FCAT1 EXCEPTIONS INVALID_PARAMETER_COMBINATION = 1 PROGRAM_ERROR = 2 TOO_MANY_LINES = 3 OTHERS = 4 . call method O_GRID2-&gt;REFRESH_TABLE_DISPLAY( ). ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Module STATUS_0200 OUTPUT *&amp;---------------------------------------------------------------------* MODULE STATUS_0200 OUTPUT. SET PF-STATUS 'ZHEADER'. " Only load header data from DB once IF lt_likp IS INITIAL. SELECT vbeln ernam erdat vstel vkorg FROM zdb_edit_alv INTO CORRESPONDING FIELDS OF TABLE lt_likp WHERE vbeln IN s_vbeln. ENDIF. " Only create container and grid once IF o_container1 IS INITIAL AND o_grid1 IS INITIAL. " Create custom container CREATE OBJECT o_container1 EXPORTING container_name = 'CONTAINER1'. " Create ALV grid object CREATE OBJECT o_grid1 EXPORTING i_parent = o_container1. " Set up field catalog and layout if needed (assuming lt_fcat and ls_layo are ready) CALL METHOD o_grid1-&gt;set_table_for_first_display EXPORTING i_structure_name = 'ZDB_EDIT_ALV' is_layout = ls_layo CHANGING it_outtab = lt_likp it_fieldcatalog = lt_fcat EXCEPTIONS invalid_parameter_combination = 1 program_error = 2 too_many_lines = 3 OTHERS = 4. " Set event handler for item-level data retrieval DATA(o_delivery) = NEW delivery( ). SET HANDLER o_delivery-&gt;get_data FOR o_grid1. ENDIF. ENDMODULE. *&amp;---------------------------------------------------------------------* *&amp; Module USER_COMMAND_0200 INPUT MODULE USER_COMMAND_0200 INPUT. CASE SY-UCOMM. WHEN 'BACK'. LEAVE PROGRAM. "Back to the program WHEN 'CREATE'. "Creating new record for header data PERFORM CREATE_HEADER_DATA. WHEN 'EDIT'. "Editable alv for header data PERFORM CHANGE_MODE. WHEN 'UPDATE'. "Updateing the record for header data PERFORM UPDATE_HEADER_DATA. WHEN 'DELETE'. "deleteing for a record for header data PERFORM DELETE_HEADER_DATA. WHEN 'SAVE'. "saveing the db table for header data PERFORM SAVE_HEADER_DATA. ENDCASE. ENDMODULE. *&amp;---------------------------------------------------------------------* *&amp; Form CHANGE_MODE *&amp;---------------------------------------------------------------------* FORM CHANGE_MODE . DATA : LT_INDEX_ROWS TYPE LVC_T_ROW, LT_ROW_NO TYPE LVC_T_ROID, LS_ROW_NO TYPE LVC_S_ROID, LS_STYLEROW TYPE LVC_S_STYL, LT_STYLEROW TYPE TABLE OF LVC_S_STYL. CALL METHOD O_GRID1-&gt;GET_SELECTED_ROWS IMPORTING * et_index_rows = lt_index_rows ET_ROW_NO = LT_ROW_NO. IF NOT LT_ROW_NO IS INITIAL. LOOP AT LT_LIKP INTO LS_LIKP. READ TABLE LT_ROW_NO INTO LS_ROW_NO WITH KEY ROW_ID = SY-TABIX. IF SY-SUBRC = 0. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VBELN'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'ERNAM'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. LS_STYLEROW-FIELDNAME = 'ERDAT'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. LS_STYLEROW-FIELDNAME = 'VSTEL'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. LS_STYLEROW-FIELDNAME = 'VKORG'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. CLEAR: LS_LIKP-CELLTAB. INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIKP-CELLTAB. MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB. CLEAR: LT_STYLEROW. ELSE. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VBELN'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'ERNAM'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'ERDAT'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VSTEL'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VKORG'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. CLEAR: LS_LIKP-CELLTAB. INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIKP-CELLTAB. MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB. CLEAR: LT_STYLEROW. ENDIF. ENDLOOP. ENDIF. CLEAR LT_ROW_NO. CLEAR LS_ROW_NO. IF O_GRID1-&gt;IS_READY_FOR_INPUT( ) EQ 0. CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. ELSE. CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. ENDIF. CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY( ). ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form CREATE_HEADER_DATA *&amp;---------------------------------------------------------------------* FORM CREATE_HEADER_DATA . DATA: LS_NEW TYPE T_ZDB_EDIT_ALV, LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY, LS_STYLEROW TYPE LVC_S_STYL. CLEAR: LS_NEW, LT_STYLEROW. " Define editable fields LS_STYLEROW-FIELDNAME = 'VBELN'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'ERNAM'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'ERDAT'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'VSTEL'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'VKORG'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. " Assign celltab to new row LS_NEW-CELLTAB = LT_STYLEROW. " Insert new row at the beginning APPEND LS_NEW TO LT_LIKP. " Set grid to editable mode CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. " Refresh ALV to reflect changes CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form DELETE_HEADER_DATA *&amp;--------------------------------------------------------------------- FORM DELETE_HEADER_DATA . DATA: LT_ROWS TYPE LVC_T_ROW, LS_ROW TYPE LVC_S_ROW, LV_IDX TYPE SY-TABIX. CALL METHOD O_GRID1-&gt;GET_SELECTED_ROWS IMPORTING ET_INDEX_ROWS = LT_ROWS. LOOP AT LT_ROWS INTO LS_ROW. LV_IDX = LS_ROW-INDEX. READ TABLE LT_LIKP INDEX LV_IDX INTO LS_LIKP. IF SY-SUBRC = 0. DELETE FROM ZDB_EDIT_ALV WHERE VBELN = LS_LIKP-VBELN and ERNAM = LS_LIKP-ERNAM. DELETE LT_LIKP INDEX LV_IDX. ENDIF. ENDLOOP. CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY. COMMIT WORK. MESSAGE 'Selected header(s) deleted' TYPE 'S'. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form SAVE_HEADER_DATA *&amp;---------------------------------------------------------------------* TYPES: BEGIN OF TY_ZDB_EDIT_ALV_FLAT, VBELN TYPE ZDB_EDIT_ALV-VBELN, ERNAM TYPE ZDB_EDIT_ALV-ERNAM, ERDAT TYPE ZDB_EDIT_ALV-ERDAT, VSTEL TYPE ZDB_EDIT_ALV-VSTEL, VKORG TYPE ZDB_EDIT_ALV-VKORG, END OF TY_ZDB_EDIT_ALV_FLAT. DATA: LS_DB_ALV_FLAT TYPE TY_ZDB_EDIT_ALV_FLAT. FORM SAVE_HEADER_DATA . DATA: LS_DB_ALV_FLAT TYPE TY_ZDB_EDIT_ALV_FLAT, LV_VBELN TYPE ZDB_EDIT_ALV-VBELN, LV_SKIPPED TYPE I VALUE 0, LT_LIKP_CLEAN TYPE TABLE OF T_ZDB_EDIT_ALV, LS_LIKP_CLEAN TYPE T_ZDB_EDIT_ALV, LV_SAVED_ROWS TYPE I VALUE 0. " Capture ALV changes CALL METHOD O_GRID1-&gt;CHECK_CHANGED_DATA. LOOP AT LT_LIKP INTO LS_LIKP. " Skip empty header rows IF LS_LIKP-VBELN IS INITIAL AND LS_LIKP-ERNAM IS INITIAL AND LS_LIKP-ERDAT IS INITIAL AND LS_LIKP-VSTEL IS INITIAL AND LS_LIKP-VKORG IS INITIAL. LV_SKIPPED = LV_SKIPPED + 1. CONTINUE. ENDIF. " Keep non-empty row for redisplay LS_LIKP_CLEAN = LS_LIKP. APPEND LS_LIKP_CLEAN TO LT_LIKP_CLEAN. " Prepare structure for DB insert/update CLEAR LS_DB_ALV_FLAT. MOVE-CORRESPONDING LS_LIKP TO LS_DB_ALV_FLAT. " Check if record exists SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_VBELN FROM ZDB_EDIT_ALV WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN. IF SY-SUBRC = 0. " Record exists -&gt; UPDATE UPDATE ZDB_EDIT_ALV SET ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM, ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT, VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL, VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN. ELSE. " Record does not exist -&gt; INSERT INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT. ENDIF. LV_SAVED_ROWS = LV_SAVED_ROWS + 1. ENDLOOP. " Replace the old internal table with the cleaned one (remove empty rows) LT_LIKP = LT_LIKP_CLEAN. COMMIT WORK. *ENDIF. " Message after save IF LV_SKIPPED &gt; 0. MESSAGE |{ LV_SKIPPED } empty header record(s) were not saved and removed.| TYPE 'I'. ELSEIF LV_SAVED_ROWS &lt; 0. MESSAGE | { LV_SAVED_ROWS } without editing or creating anything were data not saved.| TYPE 'I'. ELSE. MESSAGE 'Header data saved successfully' TYPE 'S'. ENDIF. " Lock the grid after save PERFORM DISABLE_ALL_CELLS_IN_HEADER. CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form UPDATE_HEADER_DATA *&amp;---------------------------------------------------------------------* FORM UPDATE_HEADER_DATA . CALL METHOD O_GRID1-&gt;CHECK_CHANGED_DATA. LOOP AT LT_LIKP INTO LS_LIKP. " Map to flat structure (exclude CELLTAB) LS_DB_ALV_FLAT-VBELN = LS_LIKP-VBELN. LS_DB_ALV_FLAT-ERNAM = LS_LIKP-ERNAM. LS_DB_ALV_FLAT-ERDAT = LS_LIKP-ERDAT. LS_DB_ALV_FLAT-VSTEL = LS_LIKP-VSTEL. LS_DB_ALV_FLAT-VKORG = LS_LIKP-VKORG. " Check if record exists SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(LV_VBELN) FROM ZDB_EDIT_ALV WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM. IF SY-SUBRC = 0. " Record exists -&gt; UPDATE UPDATE ZDB_EDIT_ALV SET ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT, VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL, VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM. ELSE. " Record does not exist -&gt; INSERT INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT. ENDIF. ENDLOOP. COMMIT WORK. MESSAGE 'Header data Updated successfully' TYPE 'S'. " <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Make all fields non-editable after save PERFORM DISABLE_ALL_CELLS_IN_HEADER. " <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Set ALV to non-edit mode CALL METHOD O_GRID1-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. " <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Refresh ALV display CALL METHOD O_GRID1-&gt;REFRESH_TABLE_DISPLAY. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form CHANGE_ITEMS_MODE *&amp;---------------------------------------------------------------------* FORM CHANGE_ITEMS_MODE . DATA : LT_INDEX_ROWS TYPE LVC_T_ROW, LT_ROW_NO TYPE LVC_T_ROID, LS_ROW_NO TYPE LVC_S_ROID, LS_STYLEROW TYPE LVC_S_STYL, LT_STYLEROW TYPE TABLE OF LVC_S_STYL. CALL METHOD O_GRID2-&gt;GET_SELECTED_ROWS IMPORTING * et_index_rows = lt_index_rows ET_ROW_NO = LT_ROW_NO. IF NOT LT_ROW_NO IS INITIAL. LOOP AT LT_LIPS INTO LS_LIPS. READ TABLE LT_ROW_NO INTO LS_ROW_NO WITH KEY ROW_ID = SY-TABIX. IF SY-SUBRC = 0. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VBELN'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'POSNR'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'ERNAM'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. LS_STYLEROW-FIELDNAME = 'MATNR'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. LS_STYLEROW-FIELDNAME = 'WERKS'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. CLEAR: LS_LIPS-CELLTAB. INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB. MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB. CLEAR: LT_STYLEROW. ELSE. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VBELN'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'POSNR'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'ERNAM'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'MATNR'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'WERKS'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. CLEAR: LS_LIPS-CELLTAB. INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB. MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB. CLEAR: LT_STYLEROW. ENDIF. ENDLOOP. ENDIF. CLEAR LT_ROW_NO. CLEAR LS_ROW_NO. IF O_GRID2-&gt;IS_READY_FOR_INPUT( ) EQ 0. CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. ELSE. CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. ENDIF. O_GRID2-&gt;REFRESH_TABLE_DISPLAY( ). ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form CREATE_ITEMS_DATA *&amp;--------------------------------------------------------------------- FORM CREATE_ITEMS_DATA . DATA: LS_NEW TYPE T_ZDB_EDIT_ALV1, LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY, LS_STYLEROW TYPE LVC_S_STYL. CLEAR: LS_NEW, LT_STYLEROW. " Define editable fields LS_STYLEROW-FIELDNAME = 'VBELN'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'POSNR'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'ERNAM'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'MATNR'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'WERKS'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. " Assign celltab to new row LS_NEW-CELLTAB = LT_STYLEROW. " Insert new row at the beginning APPEND LS_NEW TO LT_LIPS. " Set grid to editable mode CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. " Refresh ALV to reflect changes CALL METHOD O_GRID2-&gt;REFRESH_TABLE_DISPLAY. ENDFORM. TYPES: BEGIN OF TY_ZDB_EDIT_ALV1_FLAT, VBELN TYPE ZDB_EDIT_ALV1-VBELN, POSNR TYPE ZDB_EDIT_ALV1-POSNR, ERNAM TYPE ZDB_EDIT_ALV1-ERNAM, MATNR TYPE ZDB_EDIT_ALV1-MATNR, WERKS TYPE ZDB_EDIT_ALV1-WERKS, END OF TY_ZDB_EDIT_ALV1_FLAT. DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT. *&amp;---------------------------------------------------------------------* *&amp; Form SAVE_ITEMS_DATA *&amp;--------------------------------------------------------------------- FORM SAVE_ITEMS_DATA . DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT, LS_DB_FULL TYPE ZDB_EDIT_ALV1, LV_VBELN TYPE ZDB_EDIT_ALV1-VBELN, LV_SKIPPED TYPE I VALUE 0, LT_LIPS_CLEAN TYPE TABLE OF T_ZDB_EDIT_ALV1, LS_LIPS_CLEAN TYPE T_ZDB_EDIT_ALV1, LV_SAVED_ROWS TYPE I VALUE 0, LV_HEADER_CHECK TYPE ZDB_EDIT_ALV-VBELN. CALL METHOD O_GRID2-&gt;CHECK_CHANGED_DATA. LOOP AT LT_LIPS INTO LS_LIPS. " Skip empty item rows IF LS_LIPS-VBELN IS INITIAL AND LS_LIPS-POSNR IS INITIAL AND LS_LIPS-ERNAM IS INITIAL AND LS_LIPS-MATNR IS INITIAL AND LS_LIPS-WERKS IS INITIAL. LV_SKIPPED = LV_SKIPPED + 1. CONTINUE. ENDIF. " # Check if header exists SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_HEADER_CHECK FROM ZDB_EDIT_ALV WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_LIPS-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_LIPS-ERNAM. IF SY-SUBRC &lt;&gt; 0. LV_SKIPPED = LV_SKIPPED + 1. CONTINUE. " Don't allow saving item without header ENDIF. " Keep non-empty row LS_LIPS_CLEAN = LS_LIPS. APPEND LS_LIPS_CLEAN TO LT_LIPS_CLEAN. " Prepare flat structure CLEAR LS_DB_ALV1. MOVE-CORRESPONDING LS_LIPS TO LS_DB_ALV1. " Check if item record exists SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_VBELN FROM ZDB_EDIT_ALV1 WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM. IF SY-SUBRC = 0. " UPDATE UPDATE ZDB_EDIT_ALV1 SET MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR, WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM. ELSE. " INSERT CLEAR LS_DB_FULL. MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL. INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL. ENDIF. LV_SAVED_ROWS = LV_SAVED_ROWS + 1. ENDLOOP. LT_LIPS = LT_LIPS_CLEAN. COMMIT WORK. " <span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Final messaging IF LV_SAVED_ROWS &gt; 0. MESSAGE 'Item data saved successfully' TYPE 'S'. ELSEIF LV_SKIPPED &gt; 0. MESSAGE |{ LV_SKIPPED } item row(s) were skipped – empty or missing header.| TYPE 'I'. ELSE. MESSAGE 'No item data saved.' TYPE 'I'. ENDIF. " Make all fields non-editable after save PERFORM DISABLE_ALL_CELLS_IN_ITEMS. " Set ALV to non-edit mode CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. " Refresh ALV display CALL METHOD O_GRID2-&gt;REFRESH_TABLE_DISPLAY. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form UPDATE_ITEMS_DATA *&amp;---------------------------------------------------------------------* FORM UPDATE_ITEMS_DATA . DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT, LS_DB_FULL TYPE ZDB_EDIT_ALV1, LV_VBELN TYPE ZDB_EDIT_ALV1-VBELN. " Ensure ALV changes are captured CALL METHOD O_GRID2-&gt;CHECK_CHANGED_DATA. LOOP AT LT_LIPS INTO LS_LIPS. " Map to flat structure (exclude CELLTAB) CLEAR LS_DB_ALV1. LS_DB_ALV1-VBELN = LS_LIPS-VBELN. LS_DB_ALV1-POSNR = LS_LIPS-POSNR. LS_DB_ALV1-ERNAM = LS_LIPS-ERNAM. LS_DB_ALV1-MATNR = LS_LIPS-MATNR. LS_DB_ALV1-WERKS = LS_LIPS-WERKS. " Check if record exists in DB SELECT SINGLE VBELN INTO @S_VBELN FROM ZDB_EDIT_ALV1 WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM. IF SY-SUBRC = 0. " Record exists -&gt; UPDATE UPDATE ZDB_EDIT_ALV1 SET MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR, WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM. ELSE. " Record does not exist -&gt; INSERT CLEAR LS_DB_FULL. MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL. INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL. ENDIF. ENDLOOP. COMMIT WORK. IF SY-SUBRC &lt;&gt; 0. MESSAGE 'Item data saved successfully' TYPE 'S'. ELSE. MESSAGE 'Created new row but empty record not saved' type 'I'. ENDIF. " <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Make all fields non-editable after save PERFORM DISABLE_ALL_CELLS_IN_ITEMS. " <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Set ALV to non-edit mode CALL METHOD O_GRID2-&gt;SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. " <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Refresh ALV display CALL METHOD O_GRID2-&gt;REFRESH_TABLE_DISPLAY. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form DELETE_ITEMS_DATA *&amp;---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --&gt; p1 text * &lt;-- p2 text *----------------------------------------------------------------------* FORM DELETE_ITEMS_DATA . DATA: LT_ROWS TYPE LVC_T_ROW, LS_ROW TYPE LVC_S_ROW, LV_IDX TYPE SY-TABIX. CALL METHOD O_GRID2-&gt;GET_SELECTED_ROWS IMPORTING ET_INDEX_ROWS = LT_ROWS. LOOP AT LT_ROWS INTO LS_ROW. LV_IDX = LS_ROW-INDEX. READ TABLE LT_LIPS INDEX LV_IDX INTO LS_LIPS. IF SY-SUBRC = 0. " Corrected DELETE to use both VBELN and POSNR DELETE FROM ZDB_EDIT_ALV1 WHERE VBELN = LS_LIPS-VBELN AND POSNR = LS_LIPS-POSNR AND ERNAM = LS_LIPS-ERNAM. DELETE LT_LIPS INDEX LV_IDX. ENDIF. ENDLOOP. CALL METHOD O_GRID2-&gt;REFRESH_TABLE_DISPLAY. COMMIT WORK. MESSAGE 'Selected item(s) deleted' TYPE 'S'. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form DISABLE_ALL_CELLS_IN_HEADER *&amp;---------------------------------------------------------------------* FORM DISABLE_ALL_CELLS_IN_HEADER . DATA: LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY, LS_STYLEROW TYPE LVC_S_STYL. LOOP AT LT_LIKP INTO LS_LIKP. CLEAR LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'VBELN'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'ERNAM'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'ERDAT'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'VSTEL'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'VKORG'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. " Apply to current row LS_LIKP-CELLTAB = LT_STYLEROW. MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB. ENDLOOP. ENDFORM. *&amp;---------------------------------------------------------------------* *&amp; Form DISABLE_ALL_CELLS_IN_ITEMS *&amp;---------------------------------------------------------------------* FORM DISABLE_ALL_CELLS_IN_ITEMS . DATA: LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY, LS_STYLEROW TYPE LVC_S_STYL. LOOP AT LT_LIPS INTO LS_LIPS. CLEAR LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'VBELN'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'POSNR'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'ERNAM'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'MATNR'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'WERKS'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=&gt;MC_STYLE_DISABLED. APPEND LS_STYLEROW TO LT_STYLEROW. " Apply to current row LS_LIKP-CELLTAB = LT_STYLEROW. MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB. ENDLOOP. ENDFORM.</code></pre><P>&nbsp;</P> 2026-01-24T04:59:44.641000+01:00 https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-sap/using-custom-logic-in-sap-s-4hana-cloud-to-change-field-status-of-purchase/ba-p/14312488 Using Custom Logic in SAP S/4HANA Cloud to change field status of Purchase Requisition 2026-01-26T04:50:48.909000+01:00 Zhehui_Xia28 https://community.sap.com/t5/user/viewprofilepage/user-id/40727 <H2 id="toc-hId-1765539711" id="toc-hId-1788600803">Problem Background:</H2><P><SPAN>We received a customer request: when creating a purchase requisition, they want the Valuation Price field to be optional, but in the current system this field is mandatory.</SPAN></P><H2 id="toc-hId-1569026206" id="toc-hId-1592087298">Solution:</H2><P>Attempt to meet the requirement through custom logic using a BAdI.</P><H2 id="toc-hId-1372512701" id="toc-hId-1395573793">Analysis Steps:</H2><P>1. After searching in SAP for Me, we found a KBA&nbsp;<A href="https://me.sap.com/notes/0003322867" target="_blank" rel="noopener noreferrer">3322867 - Valuation Price field is mandatory in Create Purchase Requisitions app - SAP for Me</A> which provides a solution to this problem. So we can try to use BAdI&nbsp;<SPAN><STRONG>MM_PUR_S4_PR_FLDCNTRL_SIMPLE</STRONG> to solve this problem.</SPAN></P><P><SPAN>2. We enter APP&nbsp;<STRONG>Custom Logic&nbsp;</STRONG>to create an implementation. The description of this BAdI is "Change of Field Control for Purchase Requisitions". In the documentation, we can get more information including supported fields. "PURCHASEREQUISITIONPRICE -&nbsp;Valuation Price" is included, that means our requirement can be fulfilled by this BAdI.</SPAN></P><P>3. With this BAdI, we can set four status for supported fields of Purchase Requisition: Hidden, Read-only, Mandatory, Optional.</P><UL><LI>'-': To hide the field</LI><LI>'*': To make the field read-only</LI><LI>'+': To make the field mandatory</LI><LI>'.': To make the field optional</LI></UL><P>4. The sample code of this BAdI is quite readable and easy. Based on this problem,&nbsp;<SPAN>implement the BAdI. The specific code is as follows.</SPAN></P><pre class="lia-code-sample language-abap"><code>FIELD-SYMBOLS &lt;fs&gt; TYPE mmpur_s_pr_fldsel. READ TABLE fieldselection_table ASSIGNING &lt;fs&gt; WITH KEY field = 'PURCHASEREQUISITIONPRICE'. IF sy-subrc EQ 0. &lt;fs&gt;-fieldstatus = '.'. ENDIF.</code></pre><P>5. After testing, the BAdI works prefect. This BAdI not only supports GUI APP - <STRONG>Create Purchase Requisition - Advanced</STRONG>, but also supports Fiori APP - <STRONG>Manage Purchase Requisitions - Professional</STRONG>.</P><H2 id="toc-hId-1175999196" id="toc-hId-1199060288">Conclusion:</H2><P>By reading this article and several previous blogs on similar scenarios, I hope you now understand how to use custom logic to apply certain restrictions when creating preliminary invoices for purchase orders.<BR />You can find more information about SAP S/4HANA Cloud procurement-related issues at the following link:<SPAN>&nbsp;</SPAN><A href="https://community.sap.com/t5/c-khhcw49343/SAP+S%25252F4HANA+Cloud+Public+Edition+Sourcing+and+Procurement/pd-p/a906d110-8210-4641-9e54-4744b42f06d0" target="_self">SAP S/4HANA Cloud Public Edition Sourcing and Procurement - SAP Community</A></P><P>You can also read more blogs about SAP S/4HANA Cloud procurement at the following link:<SPAN>&nbsp;</SPAN><A href="https://community.sap.com/t5/c-khhcw49343/SAP+S%25252F4HANA+Cloud+Public+Edition+Sourcing+and+Procurement/pd-p/a906d110-8210-4641-9e54-4744b42f06d0" target="_self">SAP S/4HANA Cloud Public Edition Sourcing and Procurement - SAP Community</A></P><P>If you have any suggestions or thoughts about this article, please feel free to share them in the comments section. I look forward to communicating with you. You are also welcome to follow my personal account, and I look forward to seeing you in the next blog post!</P> 2026-01-26T04:50:48.909000+01:00 https://community.sap.com/t5/abap-blog-posts/dynamic-rap-actions-explained-abstract-entities-powering-flexible-action/ba-p/14317341 Dynamic RAP Actions Explained: Abstract Entities Powering Flexible Action Buttons 2026-02-04T08:58:36.978000+01:00 Bikash_R https://community.sap.com/t5/user/viewprofilepage/user-id/1527809 <P><U><FONT face="times new roman,times" size="4" color="#000000"><STRONG>Introduction--</STRONG></FONT></U></P><P><FONT face="times new roman,times" color="#000000"><SPAN>In the&nbsp;RESTful ABAP Programming Model (RAP),&nbsp;</SPAN><I><SPAN>actions</SPAN></I><SPAN>&nbsp;play a crucial role in triggering custom business logic on business objects — for example, approving, rejecting, or performing special updates on records.</SPAN><SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times" color="#000000"><SPAN>Sometimes, these actions require&nbsp;user inputs, such as selecting a reason code, approval type, or custom parameter value before execution. To achieve this, RAP provides&nbsp;parameterized actions, and to enhance usability, we can use an&nbsp;abstract entity&nbsp;to define the parameter structure along with a&nbsp;dropdown (value help).</SPAN><SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times" color="#000000">In this blog,&nbsp;we’ll&nbsp;explore how to build a&nbsp;parameterized RAP action&nbsp;that displays a dropdown list for user&nbsp;selection, powered by an&nbsp;abstract entity. This approach keeps the core logic clean, reusable, and consistent with RAP’s “clean core” principles.&nbsp;</FONT></P><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Objective--</STRONG></FONT></U></FONT></P><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>By the end of this blog,&nbsp;you’ll&nbsp;learn how to: -</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times">Define an&nbsp;abstract entity&nbsp;to&nbsp;represent&nbsp;the action parameters&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">Provide a&nbsp;dropdown&nbsp;for the parameter field&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">Link the abstract entity to the&nbsp;RAP action definition&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">Implement the&nbsp;behavior logic&nbsp;to handle user input&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">Execute and test the action from the&nbsp;Fiori Elements UI</FONT></LI></UL><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Business Scenario Overview--</STRONG></FONT></U></FONT></P><P><FONT face="times new roman,times">You are designing a&nbsp;Purchase Order (PO) Management RAP application, consisting of a&nbsp;Header&nbsp;and&nbsp;Item&nbsp;structure.&nbsp;</FONT></P><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>The goal: -</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times">To&nbsp;release purchase orders&nbsp;(POs) from Fiori using a&nbsp;parameterized action.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">The action uses an&nbsp;abstract entity&nbsp;to capture runtime parameters (like&nbsp;release&nbsp;flag).&nbsp;</FONT></LI></UL><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Database Tables--</STRONG></FONT></U></FONT></P><P><FONT face="times new roman,times" size="4"><STRONG>Header Table:&nbsp;ZBRT_T_PO_HRD</STRONG>&nbsp;</FONT></P><P><FONT face="times new roman,times" size="4"><STRONG>This table stores high-level details of a purchase order</STRONG>.&nbsp;</FONT></P><pre class="lia-code-sample language-abap"><code>@EndUserText.label : 'Purchase order header table' @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE @AbapCatalog.tableCategory : #TRANSPARENT @AbapCatalog.deliveryClass : #A @AbapCatalog.dataMaintenance : #RESTRICTED define table zbrt_t_po_hrd { key mandt : abap.clnt not null; key ebeln : ebeln not null; bukrs : abap.char(4); supplier : abap.char(10); bsart : abap.char(4); lifnr : abap.char(10); land1 : abap.char(2); country_desc : abap.char(40); po_release : abap.char(1); migo_status : abap.char(40); email : abap.char(60); lastdatetime : timestampl; }</code></pre><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Key&nbsp;points:--</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times">EBELN&nbsp;is the primary key.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">lastdatetime&nbsp;acts as the&nbsp;ETag&nbsp;for draft handling and concurrency control.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">po_release&nbsp;indicates&nbsp;whether the PO has been released or not.&nbsp;</FONT></LI></UL><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Item Table: ZBRT_T_PO_ITEM--</STRONG></FONT></U></FONT></P><P><FONT face="times new roman,times"><STRONG>This stores&nbsp;item-level details&nbsp;linked to the header via a foreign key.</STRONG>&nbsp;</FONT></P><pre class="lia-code-sample language-abap"><code>@EndUserText.label : 'Purchase order item table' @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE @AbapCatalog.tableCategory : #TRANSPARENT @AbapCatalog.deliveryClass : #A @AbapCatalog.dataMaintenance : #RESTRICTED define table zbrt_t_po_item { key mandt : abap.clnt not null; @AbapCatalog.foreignKey.screenCheck : false key ebeln : ebeln not null with foreign key [1..*,1] zbrt_t_po_hrd where mandt = zbrt_t_po_item.mandt and ebeln = zbrt_t_po_item.ebeln; key ebelp : abap.numc(5) not null; matnr : abap.char(40); werks : abap.char(4); lgort : abap.char(4); @Semantics.quantity.unitOfMeasure : 'zbrt_t_po_item.meins' menge : abap.quan(12,2); meins : abap.unit(3); @Semantics.amount.currencyCode : 'zbrt_t_po_item.waers' netpr : abap.curr(15,2); waers : abap.cuky; lastdatechanged : timestampl; }</code></pre><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Key&nbsp;points:-</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times">The association&nbsp;[1..*,1]&nbsp;means:&nbsp;Many items&nbsp;can belong to&nbsp;one header.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">Semantic annotations help map units and currencies for UI display.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">lastdatechanged&nbsp;helps track data changes per item.&nbsp;</FONT></LI></UL><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Abstract Entity: ZBRT_POPUP-</STRONG></FONT></U></FONT></P><P><FONT face="times new roman,times">Abstract entities are&nbsp;not physical tables; they are used for&nbsp;data transfer or parameter passing.&nbsp;</FONT></P><P><FONT face="times new roman,times">In this case,&nbsp;it’s&nbsp;used as a&nbsp;parameter popup&nbsp;entity during your&nbsp;action execution&nbsp;(e.g., PO release).&nbsp;</FONT></P><pre class="lia-code-sample language-abap"><code>@EndUserText.label: 'PO RELEASE' @Metadata.allowExtensions: true define abstract entity zbrt_popup { @UI.defaultValue: 'X' @EndUserText.label: 'po_release' po_release : abap.char( 1 ); }</code></pre><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Purpose:-</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times">Used as a&nbsp;popup parameter&nbsp;for a RAP&nbsp;parameterized action.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">When the user triggers the&nbsp;<I>Release PO</I>&nbsp;action in the Fiori UI, this abstract entity is displayed to capture&nbsp;additional&nbsp;inputs (like “Release Flag”).&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">It is&nbsp;decoupled&nbsp;from the database, acting only as a&nbsp;temporary input structure.&nbsp;</FONT></LI></UL><P><FONT face="times new roman,times" size="4"><STRONG>Interface View for Header: ZC_BRT_PO_HEAD--</STRONG>&nbsp;</FONT></P><P><FONT face="times new roman,times" size="4"><STRONG>This is the&nbsp;Root Entity&nbsp;of your RAP Business Object.</STRONG>&nbsp;</FONT></P><pre class="lia-code-sample language-abap"><code>@AbapCatalog.viewEnhancementCategory: [#NONE] @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Projection view for header' @Metadata.ignorePropagatedAnnotations: true @ObjectModel.usageType:{ serviceQuality: #X, sizeCategory: #S, dataClass: #MIXED } @Metadata.allowExtensions: true define root view entity zc_brt_po_head as select from zbrt_t_po_hrd composition [1..*] of zc_brt_po_item as _item { key ebeln, bukrs, supplier, bsart, lifnr, land1, country_desc, po_release, migo_status, email, @Semantics.systemDateTime.localInstanceLastChangedAt: true lastdatetime, cast('3' as abap.char(1)) as porelease, cast('1' as abap.char(1)) as noporelease, _item }</code></pre><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Key concepts:-</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times"><STRONG>root view entity</STRONG>: Marks it as the&nbsp;root node&nbsp;of the RAP Business Object.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG>composition [1..*] of _item</STRONG>:&nbsp;Establishes&nbsp;a&nbsp;header–item relationship&nbsp;(1 header → many items).&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG><I>@Semantics.systemDateTime.localInstanceLastChangedAt</I></STRONG>: Enables&nbsp;ETag-based&nbsp;draft and lock management.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG>cast('3' as&nbsp;abap.char(1)) as&nbsp;porelease</STRONG>:&nbsp;&nbsp;Defines&nbsp;a&nbsp;calculated field&nbsp;named&nbsp;porelease. This is a constant value ('3') cast to a character of length 1. It is typically used to&nbsp;represent&nbsp;a&nbsp;fixed feature control&nbsp;value (e.g., enabling a 'Release PO' button on the UI).&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG>cast('1' as&nbsp;abap.char(1)) as&nbsp;noporelease</STRONG>:&nbsp;Defines another&nbsp;calculated field&nbsp;named&nbsp;noporelease&nbsp;with a constant value of&nbsp;'1'.&nbsp;Similar to&nbsp;above, this could be used for feature control (e.g., disabling a 'No Release' button).&nbsp;</FONT></LI></UL><P><FONT face="times new roman,times" size="4"><STRONG>Interface View for Item: ZC_BRT_PO_ITEM--</STRONG>&nbsp;</FONT></P><P><FONT face="times new roman,times" size="4"><STRONG>This is the&nbsp;child entity&nbsp;linked to the header.</STRONG>&nbsp;</FONT></P><pre class="lia-code-sample language-abap"><code>@AbapCatalog.viewEnhancementCategory: [#NONE] @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Projection view for item' @Metadata.ignorePropagatedAnnotations: true @ObjectModel.usageType:{ serviceQuality: #X, sizeCategory: #S, dataClass: #MIXED } @Metadata.allowExtensions: true define view entity zc_brt_po_item as select from zbrt_t_po_item association to parent zc_brt_po_head as _head on $projection.ebeln = _head.ebeln { key ebeln, key ebelp, matnr, werks, lgort, @Semantics.quantity.unitOfMeasure: 'Meins' menge, meins, @Semantics.amount.currencyCode: 'Waers' netpr, waers, @Semantics.systemDateTime.localInstanceLastChangedAt: true lastdatechanged, _head }</code></pre><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Explanation:-</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times">This view&nbsp;represents&nbsp;the&nbsp;<STRONG>item-level node</STRONG>&nbsp;in your RAP BO.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">_head&nbsp;is a&nbsp;<STRONG>public association</STRONG>&nbsp;to navigate back to the header.&nbsp;</FONT></LI></UL><UL><LI><FONT face="times new roman,times">The same&nbsp;<STRONG>ETag annotation</STRONG>&nbsp;(<STRONG><I>@Semantics.systemDateTime.localInstanceLastChangedAt</I></STRONG>) ensures concurrency management for items too.&nbsp;</FONT></LI></UL><P><FONT face="times new roman,times" size="4"><U><STRONG>Then design the&nbsp;behavior&nbsp;definition-</STRONG></U></FONT></P><pre class="lia-code-sample language-abap"><code>managed implementation in class zbp_c_brt_po_head unique; strict ( 2 ); with draft; define behavior for zc_brt_po_head //alias &lt;alias_name&gt; persistent table zbrt_t_po_hrd lock master total etag Lastdatetime draft table zbrt_t_h_dft authorization master ( instance ) etag master lastdatetime { create ( precheck ) { default function GetDefaultsForCreate; } update ( precheck, features : instance ); delete ( precheck, features : instance ); field ( readonly ) bsart, Country_Desc; field ( mandatory ) bukrs; field ( readonly : create ) po_release; association _item { create; with draft; } mapping for zbrt_t_po_hrd { bsart = bsart; bukrs = bukrs; country_desc = country_desc; ebeln = ebeln; land1 = land1; lastdatetime = lastdatetime; lifnr = lifnr; migo_status = migo_status; porelease = po_release; email = email; } validation check_email on save { field Email; } determination migo_status_update on modify { field porelease; } action ( features : instance ) POREL parameter zbrt_popup result [1] $self; action ( features : instance ) PONOREL result [1] $self; static action Static_ALL result [1] $self; draft action Activate optimized; draft action Edit; draft action Resume; draft action Discard; draft determine action Prepare; } define behavior for zc_brt_po_item //alias &lt;alias_name&gt; persistent table zbrt_t_po_item lock dependent by _head draft table zbrt_t_i_ft authorization dependent by _head etag master Lastdatechanged { update; delete; field ( readonly ) ebeln, ebelp; association _head; }</code></pre><pre class="lia-code-sample language-abap"><code>determination migo_status_update on modify { field porelease; }</code></pre><P><FONT face="times new roman,times"><SPAN>Automatically updates&nbsp;</SPAN><STRONG><SPAN>MIGO status</SPAN></STRONG><SPAN>&nbsp;whenever the&nbsp;</SPAN><STRONG><SPAN>PO Release</SPAN></STRONG><SPAN>&nbsp;field changes.</SPAN></FONT></P><pre class="lia-code-sample language-abap"><code>action ( features : instance ) POREL parameter zbrt_popup result [1] $self; action ( features : instance ) PONOREL result [1] $self; static action Static_ALL result [1] $self;</code></pre><UL><LI><FONT face="times new roman,times"><STRONG><SPAN>POREL</SPAN></STRONG><SPAN>&nbsp;→ Triggered to release a purchase order (with parameter&nbsp;popup).</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG><SPAN>PONOREL</SPAN></STRONG><SPAN>&nbsp;→ Reverses release.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG><SPAN>Static_ALL</SPAN></STRONG><SPAN>&nbsp;→ Static action (not tied to any instance).</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><P><FONT size="4" color="#000000"><U><STRONG><FONT face="times new roman,times"><SPAN class="">Metadata extension--</SPAN></FONT></STRONG></U></FONT></P><pre class="lia-code-sample language-abap"><code>@Metadata.layer: #CORE @UI:{ headerInfo:{ title:{ value: 'Ebeln'}, description:{value: 'Migo_Status' }, typeName: 'Purchase Order Data', typeNamePlural: 'Purchase Order Data' } } annotate view zc_brt_po_head with { @UI.facet: [ { position: 10, label: 'PO Header', type: #IDENTIFICATION_REFERENCE }, { position: 20 , label: 'PO Item' , type: #LINEITEM_REFERENCE , targetElement: '_item' } ] @UI.identification: [ { position: 10, label: 'PO Number' } , { type: #FOR_ACTION_GROUP, label: 'PO Release Options', actionGroupId: '_ClickRelease' }, { type: #FOR_ACTION, label: 'PO Release', dataAction: 'POREL', actionGroupId: '_ClickRelease' }, { type: #FOR_ACTION, label: 'PO NotRelease', dataAction: 'PONOREL', actionGroupId: '_ClickRelease' } ] @UI.lineItem: [ { position: 10, label: 'PO Number' } , { type: #FOR_ACTION_GROUP, label: 'PO Release Options', actionGroupId: '_ClickRelease' }, { type: #FOR_ACTION, label: 'PO Release', dataAction: 'POREL', actionGroupId: '_ClickRelease' }, { type: #FOR_ACTION, label: 'PO NotRelease', dataAction: 'PONOREL', actionGroupId: '_ClickRelease' } , //This button we will use as static button { type: #FOR_ACTION, label: 'Release All POs', dataAction: 'Static_ALL',actionGroupId: '_ClickRelease' } ] @UI.selectionField: [ { position: 10 } ] @EndUserText.label: 'PO Number' ebeln; @UI.identification: [ { position: 20 , label: 'Company Code' } ] @UI.lineItem: [ { position: 20 , label: 'Company Code' } ] @UI.selectionField: [ { position: 20 } ] @EndUserText.label: 'Company Code' bukrs; @EndUserText.label: 'Document Type' @UI.identification: [ { position: 40 , label: 'Document Type' } ] @UI.lineItem: [ { position: 40 , label: 'Document Type' } ] @UI.selectionField: [ { position: 40 } ] bsart; @EndUserText.label: 'Vendor' @UI.identification: [ { position: 50 , label: 'Vendor' } ] @UI.lineItem: [ { position: 50 , label: 'Vendor' } ] @UI.selectionField: [ { position: 50 } ] lifnr; @EndUserText.label: 'Country' @UI.identification: [ { position: 60 , label: 'Country' } ] @UI.lineItem: [ { position: 60 , label: 'Country' } ] @UI.selectionField: [ { position: 60 } ] land1; @EndUserText.label: 'Country Name' @UI.identification: [ { position: 70 , label: 'Country Name' } ] @UI.lineItem: [ { position: 70 , label: 'Country Name' } ] @UI.selectionField: [ { position: 70 } ] country_desc; @EndUserText.label: 'PO Release' @UI.identification: [ { position: 80 , label: 'PO Release' } ] @UI.lineItem: [ { position: 80 , label: 'PO Release' } ] @UI.selectionField: [ { position: 80 } ] po_release; @EndUserText.label: 'MIGO Status' @UI.identification: [ { position: 90 , label: 'MIGO Status' } ] @UI.lineItem: [ { position: 90 , label: 'MIGO Status' } ] @UI.selectionField: [ { position: 90 } ] migo_status; @EndUserText.label: 'Email ID' @UI.identification: [ { position: 100 , label: 'Email ID' } ] @UI.lineItem: [ { position: 100 , label: 'Email ID' } ] @UI.selectionField: [ { position: 100 } ] email; @UI.identification: [ { position: 110, label: 'Change Date Time' } ] @UI.lineItem: [ { position: 110, label: 'Change Date Time' } ] @UI.selectionField: [ { position: 110 } ] @EndUserText.label: 'Change Date Time' lastdatetime; }</code></pre><P><FONT face="times new roman,times"><SPAN class="">This is the<SPAN>&nbsp;</SPAN></SPAN><SPAN class="">Metadata Extension (UI annotations)</SPAN><SPAN class=""><SPAN>&nbsp;</SPAN>for<SPAN>&nbsp;</SPAN></SPAN><SPAN class="">RAP Purchase Order application--</SPAN><SPAN class=""><SPAN>&nbsp;</SPAN>it defines how the fields and actions from our behavior definition (zc_brt_po_head) appear in the<SPAN>&nbsp;</SPAN></SPAN><SPAN class="">Fiori Elements app (List Report/Object Page)</SPAN><SPAN class="">.</SPAN><SPAN class="">&nbsp;</SPAN></FONT></P><pre class="lia-code-sample language-abap"><code>.identification: [ { position: 10, label: 'PO Number' } , { type: #FOR_ACTION_GROUP, label: 'PO Release Options', actionGroupId: '_ClickRelease' }, { type: #FOR_ACTION, label: 'PO Release', dataAction: 'POREL', actionGroupId: '_ClickRelease' }, { type: #FOR_ACTION, label: 'PO NotRelease', dataAction: 'PONOREL', actionGroupId: '_ClickRelease' } ]</code></pre><P><FONT face="times new roman,times" size="4"><STRONG><SPAN>These create&nbsp;grouped action buttons&nbsp;and drop-down&nbsp;on both the&nbsp;List Report and Object Page:-</SPAN></STRONG></FONT></P><UL><LI><FONT face="times new roman,times"><STRONG><SPAN>PO Release Options</SPAN></STRONG><SPAN>&nbsp;→ Acts as a dropdown group.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>Inside it:</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG><SPAN>PO Release</SPAN></STRONG><SPAN>&nbsp;→ Triggers the&nbsp;POREL&nbsp;action (for releasing PO).</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><STRONG><SPAN>PO&nbsp;NotRelease</SPAN></STRONG><SPAN>&nbsp;→ Triggers&nbsp;PONOREL&nbsp;action (for cancelling release).</SPAN><SPAN>&nbsp;</SPAN></FONT></LI><LI><FONT face="times new roman,times"><STRONG><SPAN>Release All POs</SPAN></STRONG><SPAN>&nbsp;→ Added later as a&nbsp;</SPAN><STRONG><SPAN>static action</SPAN></STRONG><SPAN>.</SPAN></FONT></LI></UL><pre class="lia-code-sample language-abap"><code>{ type: #FOR_ACTION, label: 'Release All POs', dataAction: 'Static_ALL', actionGroupId: '_ClickRelease' }</code></pre><P><FONT face="times new roman,times"><STRONG><SPAN>This button executes the&nbsp;Static Action&nbsp;(Static_ALL) — useful for mass operations like&nbsp;</SPAN></STRONG><STRONG><I><SPAN>“Release All Purchase Orders”</SPAN></I></STRONG><STRONG><SPAN>&nbsp;without selecting individual ones.</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times"><STRONG><SPAN>Then implement the logic in the behavior implementation class for validation,&nbsp;actions&nbsp;and determination--</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P><pre class="lia-code-sample language-abap"><code>CLASS lhc_zc_brt_po_head DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS get_instance_features FOR INSTANCE FEATURES IMPORTING keys REQUEST requested_features FOR zc_brt_po_head RESULT result. METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION IMPORTING keys REQUEST requested_authorizations FOR zc_brt_po_head RESULT result. METHODS precheck_create FOR PRECHECK IMPORTING entities FOR CREATE zc_brt_po_head. METHODS precheck_update FOR PRECHECK IMPORTING entities FOR UPDATE zc_brt_po_head. METHODS precheck_delete FOR PRECHECK IMPORTING keys FOR DELETE zc_brt_po_head. METHODS GetDefaultsForCreate FOR READ IMPORTING keys FOR FUNCTION zc_brt_po_head~GetDefaultsForCreate RESULT result. METHODS ponorel FOR MODIFY IMPORTING keys FOR ACTION zc_brt_po_head~ponorel RESULT result. METHODS porel FOR MODIFY IMPORTING keys FOR ACTION zc_brt_po_head~porel RESULT result. METHODS Static_ALL FOR MODIFY IMPORTING keys FOR ACTION zc_brt_po_head~Static_ALL RESULT result. METHODS migo_status_update FOR DETERMINE ON MODIFY IMPORTING keys FOR zc_brt_po_head~migo_status_update. METHODS check_email FOR VALIDATE ON SAVE IMPORTING keys FOR zc_brt_po_head~check_email. ENDCLASS. CLASS lhc_zc_brt_po_head IMPLEMENTATION. METHOD get_instance_features. ENDMETHOD. METHOD get_instance_authorizations. ENDMETHOD. METHOD precheck_create. LOOP AT entities INTO DATA(ls_enity). IF ls_enity-bukrs EQ '6000'. APPEND VALUE #( ebeln = ls_enity-ebeln ) TO failed-zc_brt_po_head. APPEND VALUE #( ebeln = ls_enity-ebeln %msg = new_message_with_text( severity = if_abap_behv_message=&gt;severity-error text = 'Please enter correct Company Code' &amp;&amp; ls_enity- bukrs ) ) TO reported-zc_brt_po_head. ENDIF. ENDLOOP. ENDMETHOD. METHOD precheck_update. LOOP AT entities INTO DATA(ls_enity). IF ls_enity-bukrs EQ '6000'. APPEND VALUE #( ebeln = ls_enity-ebeln ) TO failed-zc_brt_po_head. APPEND VALUE #( ebeln = ls_enity-ebeln %msg = new_message_with_text( severity = if_abap_behv_message=&gt;severity-error text = 'Please enter correct Company Code' &amp;&amp; ls_enity-Bukrs ) ) TO reported-zc_brt_po_head. ENDIF. ENDLOOP. ENDMETHOD. METHOD precheck_delete. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( FOR ls_key IN keys ( ebeln = ls_key-ebeln ) ) RESULT DATA(lt_prechk_delete). LOOP AT lt_prechk_delete INTO DATA(ls_enity). IF ls_enity-porelease EQ abap_true. APPEND VALUE #( ebeln = ls_enity-ebeln ) TO failed-zc_brt_po_head. APPEND VALUE #( ebeln = ls_enity-ebeln %msg = new_message_with_text( severity = if_abap_behv_message=&gt;severity-error text = 'You can not delete this line Item as PO release is X' ) ) TO reported-zc_brt_po_head. ENDIF. ENDLOOP. ENDMETHOD. METHOD GetDefaultsForCreate. APPEND VALUE #( %cid = keys[ 1 ]-%cid %param-bsart = 'ZNB' ) TO result. ENDMETHOD. METHOD ponorel. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( FOR ls_key IN keys ( ebeln = ls_key-ebeln ) ) RESULT DATA(lt_po_action). LOOP AT lt_po_action ASSIGNING FIELD-SYMBOL(&lt;fs_po_action&gt;). MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( porelease ) WITH VALUE #( ( ebeln = &lt;fs_po_action&gt;-ebeln porelease = abap_false ) ) REPORTED reported FAILED failed. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( ( ebeln = &lt;fs_po_action&gt;-ebeln ) ) RESULT DATA(lt_result). result = VALUE #( FOR ls_result IN lt_result ( ebeln = ls_result-ebeln %param-ebeln = ls_result-ebeln %param-porelease = ls_result-porelease ) ). ENDLOOP. ENDMETHOD. METHOD porel. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;fs_po_action&gt;). DATA(lv_popup_value) = &lt;fs_po_action&gt;-%param-po_release. MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( po_release ) WITH VALUE #( ( Ebeln = &lt;fs_po_action&gt;-Ebeln po_release = lv_popup_value ) ) REPORTED reported FAILED failed. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( ( Ebeln = &lt;fs_po_action&gt;-Ebeln ) ) RESULT DATA(lt_result). result = VALUE #( FOR ls_result IN lt_result ( ebeln = ls_result-Ebeln %param-ebeln = ls_result-ebeln %param-po_release = ls_result-po_release ) ). ENDLOOP. ENDMETHOD. METHOD Static_ALL. SELECT FROM zbrt_t_po_hrd FIELDS ebeln , po_release WHERE po_release = _false INTO TABLE(lt_static_act). LOOP AT lt_static_act INTO DATA(ls_static_action). MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( porelease ) WITH VALUE #( ( ebeln = ls_static_action-ebeln porelease = abap_true ) ) . READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( ( ebeln = ls_static_action-ebeln ) ) RESULT DATA(lt_result). result = VALUE #( FOR ls_result IN lt_result ( %param-ebeln = ls_result-ebeln %param-porelease = ls_result-porelease ) ). ENDLOOP. INSERT VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=&gt;severity-success text = |{ lines( lt_static_act ) } Records has been upadted | ) ) INTO TABLE reported-zc_brt_po_head. ENDMETHOD. METHOD migo_status_update. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( FOR ls_key IN keys ( ebeln = ls_key-ebeln ) ) RESULT DATA(lt_migo_status). LOOP AT lt_migo_status ASSIGNING FIELD-SYMBOL(&lt;fs_migo&gt;). IF &lt;fs_migo&gt;-porelease EQ abap_true. MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( migo_status ) WITH VALUE #( ( ebeln = &lt;fs_migo&gt;-ebeln migo_status = 'GR has done' ) ). ELSEIF &lt;fs_migo&gt;-porelease EQ abap_false. MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( migo_status ) WITH VALUE #( ( ebeln = &lt;fs_migo&gt;-ebeln migo_status = 'Open' ) ). ENDIF. ENDLOOP. ENDMETHOD. METHOD check_email. DATA: lr_reg TYPE REF TO cl_abap_regex. DATA: lr_matcher TYPE REF TO cl_abap_matcher, lv_email TYPE string. CREATE OBJECT lr_reg EXPORTING pattern = '\w+(\.\w+)*@(\w+\.)+(\w{2,4})' ignore_case = abap_true. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( FOR ls_key IN keys ( Ebeln = ls_key-Ebeln ) ) RESULT DATA(lt_validation). LOOP AT lt_validation INTO DATA(ls_validation). DATA(lv_po_count) = strlen( ls_validation-Email ). IF lv_po_count LT 10. APPEND VALUE #( Ebeln = ls_validation-Ebeln ) TO failed-zc_brt_po_head. APPEND VALUE #( Ebeln = ls_validation-Ebeln %msg = new_message_with_text( severity = if_abap_behv_message=&gt;severity-error text = 'Pls enter correct length for Email' &amp;&amp; ls_validation-Email ) ) TO reported-zc_brt_po_head. ENDIF. lr_matcher = lr_reg-&gt;create_matcher( text = ls_validation-Email ). IF lr_matcher-&gt;match( ) IS INITIAL. APPEND VALUE #( Ebeln = ls_validation-Ebeln ) TO failed-zc_brt_po_head. APPEND VALUE #( Ebeln = ls_validation-Ebeln %msg = new_message_with_text( severity = if_abap_behv_message=&gt;severity-error text = 'Pls enter correct format for Email Id' &amp;&amp; ls_validation-Email ) ) TO reported-zc_brt_po_head. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS.</code></pre><pre class="lia-code-sample language-abap"><code>METHOD ponorel. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( FOR ls_key IN keys ( ebeln = ls_key-ebeln ) ) RESULT DATA(lt_po_action). LOOP AT lt_po_action ASSIGNING FIELD-SYMBOL(&lt;fs_po_action&gt;). MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( porelease ) WITH VALUE #( ( ebeln = &lt;fs_po_action&gt;-ebeln porelease = abap_false ) ) REPORTED reported FAILED failed. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( ( ebeln = &lt;fs_po_action&gt;-ebeln ) ) RESULT DATA(lt_result). result = VALUE #( FOR ls_result IN lt_result ( ebeln = ls_result-ebeln %param-ebeln = ls_result-ebeln %param-porelease = ls_result-porelease ) ). ENDLOOP. ENDMETHOD. </code></pre><P><FONT face="times new roman,times" size="4"><STRONG><SPAN>Purpose of the Method--</SPAN></STRONG></FONT></P><P><FONT face="times new roman,times"><SPAN>ponorel&nbsp;is triggered when a user clicks the&nbsp;</SPAN><STRONG><SPAN>“PO Not Release”</SPAN></STRONG><SPAN>&nbsp;button in Fiori.</SPAN><SPAN>&nbsp;<BR /></SPAN><SPAN>Its job is to:</SPAN><SPAN>&nbsp;</SPAN></FONT></P><OL><LI><FONT face="times new roman,times"><SPAN>Read the&nbsp;</SPAN><STRONG><SPAN>selected PO(s)</SPAN></STRONG><SPAN>&nbsp;from the&nbsp;frontend.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI><LI><FONT face="times new roman,times"><SPAN>Update their&nbsp;</SPAN><STRONG><SPAN>porelease&nbsp;field to false</SPAN></STRONG><SPAN>.</SPAN></FONT></LI><LI><FONT face="times new roman,times"><SPAN>Return the updated PO information back to the&nbsp;frontend&nbsp;so the UI reflects the change.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></OL><TABLE border="2"><TBODY><TR><TD width="215.948px" height="51px"><P><FONT face="times new roman,times"><STRONG><SPAN>Step</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="312.177px" height="51px"><P><FONT face="times new roman,times"><STRONG><SPAN>Purpose</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="215.948px" height="50px"><P><FONT face="times new roman,times"><SPAN>Read entity from local mode</SPAN></FONT></P></TD><TD width="312.177px" height="50px"><P><FONT face="times new roman,times"><SPAN>Fetch selected POs from draft/local buffer</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="215.948px" height="50px"><P><FONT face="times new roman,times"><SPAN>Loop through POs</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="312.177px" height="50px"><P><FONT face="times new roman,times"><SPAN>Process each PO individually</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="215.948px" height="50px"><P><FONT face="times new roman,times"><SPAN>Modify entity</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="312.177px" height="50px"><P><FONT face="times new roman,times"><SPAN>Set&nbsp;</SPAN><SPAN>porelease&nbsp;= false</SPAN><SPAN>&nbsp;(Not Released)</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="215.948px" height="50px"><P><FONT face="times new roman,times"><SPAN>Read back updated record</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="312.177px" height="50px"><P><FONT face="times new roman,times"><SPAN>Get latest values for UI</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="215.948px" height="51px"><P><SPAN>Assign to&nbsp;</SPAN><SPAN>result</SPAN><SPAN>&nbsp;</SPAN></P></TD><TD width="312.177px" height="51px"><P><SPAN>Send updated record(s) back to Fiori</SPAN><SPAN>&nbsp;</SPAN></P></TD></TR></TBODY></TABLE><pre class="lia-code-sample language-abap"><code>METHOD porel. LOOP AT keys ASSIGNING FIELD-SYMBOL(&lt;fs_po_action&gt;). DATA(lv_popup_value) = &lt;fs_po_action&gt;-%param-po_release. MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( po_release ) WITH VALUE #( ( Ebeln = &lt;fs_po_action&gt;-Ebeln po_release = lv_popup_value ) ) REPORTED reported FAILED failed. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( ( Ebeln = &lt;fs_po_action&gt;-Ebeln ) ) RESULT DATA(lt_result). result = VALUE #( FOR ls_result IN lt_result ( ebeln = ls_result-Ebeln %param-ebeln = ls_result-ebeln %param-po_release = ls_result-po_release ) ). ENDLOOP. ENDMETHOD. </code></pre><P><FONT face="times new roman,times" size="4"><STRONG><SPAN>Purpose of the Method--</SPAN></STRONG></FONT></P><P><FONT face="times new roman,times"><SPAN>porel&nbsp;is triggered when a user clicks the&nbsp;</SPAN><STRONG><SPAN>“PO Release”</SPAN></STRONG><SPAN>&nbsp;button in Fiori.</SPAN><SPAN>&nbsp;<BR /></SPAN><SPAN>Its job is to:</SPAN><SPAN>&nbsp;</SPAN></FONT></P><OL><LI><FONT face="times new roman,times"><SPAN>Read the&nbsp;</SPAN><STRONG><SPAN>selected POs</SPAN></STRONG><SPAN>&nbsp;from the&nbsp;frontend.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI><LI><FONT face="times new roman,times"><SPAN>Update their&nbsp;</SPAN><STRONG><SPAN>po_release&nbsp;field</SPAN></STRONG><SPAN>&nbsp;based on the value passed from the frontend (%param-po_release).</SPAN></FONT></LI><LI><FONT face="times new roman,times"><SPAN>Return the updated PO(s) back to the&nbsp;frontend&nbsp;so the UI reflects the change.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></OL><TABLE border="2"><TBODY><TR><TD><P><FONT face="times new roman,times"><STRONG><SPAN>Feature</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><STRONG><SPAN>ponorel</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><STRONG><SPAN>porel</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD><P><FONT face="times new roman,times"><SPAN>po_release&nbsp;update</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>Always sets to&nbsp;false</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>Sets dynamically from frontend&nbsp;%param-po_release</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD><P><FONT face="times new roman,times"><SPAN>Use case</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>“PO Not Release” button</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>“PO Release” button or popup</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD><P><FONT face="times new roman,times"><SPAN>Logic</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>Hard-coded</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>Dynamic based on action parameter</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR></TBODY></TABLE><pre class="lia-code-sample language-abap"><code>METHOD Static_ALL. SELECT FROM zbrt_t_po_hrd FIELDS ebeln , po_release WHERE po_release = _false INTO TABLE (lt_static_act). LOOP AT lt_static_act INTO DATA(ls_static_action). MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( porelease ) WITH VALUE #( ( ebeln = ls_static_action-ebeln porelease = abap_true ) ) . READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE #( ( ebeln = ls_static_action-ebeln ) ) RESULT DATA(lt_result). result = VALUE #( FOR ls_result IN lt_result ( %param-ebeln = ls_result-ebeln %param-porelease = ls_result-porelease ) ). ENDLOOP. INSERT VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=&gt;severity-success text = |{ lines( lt_static_act ) } Records has been upadted | ) ) INTO TABLE reported-zc_brt_po_head. ENDMETHOD.</code></pre><P><FONT face="times new roman,times" size="4"><STRONG><SPAN>Purpose of&nbsp;Static_ALL--</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P><UL><LI><FONT face="times new roman,times"><SPAN>This method is typically triggered by a&nbsp;</SPAN><STRONG><SPAN>“Release All POs”</SPAN></STRONG><SPAN>&nbsp;button in Fiori.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>It automatically sets&nbsp;</SPAN><STRONG><SPAN>all POs with&nbsp;porelease&nbsp;= false</SPAN></STRONG><SPAN>&nbsp;to&nbsp;true.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>Provides a&nbsp;</SPAN><STRONG><SPAN>success message</SPAN></STRONG><SPAN>&nbsp;for the user showing how many POs were updated.</SPAN></FONT></LI></UL><TABLE border="2"><TBODY><TR><TD width="45.4948px"><P><FONT face="times new roman,times"><STRONG><SPAN>Step</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="352.995px"><P><FONT face="times new roman,times"><STRONG><SPAN>Action</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="45.4948px"><P><FONT face="times new roman,times"><SPAN>1</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="352.995px"><P><FONT face="times new roman,times"><SPAN>Select all unreleased POs from DB</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="45.4948px"><P><FONT face="times new roman,times"><SPAN>2</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="352.995px"><P><FONT face="times new roman,times"><SPAN>Loop through them</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="45.4948px"><P><FONT face="times new roman,times"><SPAN>3</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="352.995px"><P><FONT face="times new roman,times"><SPAN>Set&nbsp;</SPAN><SPAN>porelease&nbsp;= true</SPAN><SPAN>&nbsp;in local/draft mode</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="45.4948px"><P><FONT face="times new roman,times"><SPAN>4</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="352.995px"><P><FONT face="times new roman,times"><SPAN>Read the updated record</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="45.4948px"><P><FONT face="times new roman,times"><SPAN>5</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="352.995px"><P><FONT face="times new roman,times"><SPAN>Return updated data to frontend</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD width="45.4948px"><P><FONT face="times new roman,times"><SPAN>6</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD><TD width="352.995px"><P><FONT face="times new roman,times"><SPAN>Insert a success message in&nbsp;</SPAN><SPAN>reported-zc_brt_po_head</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR></TBODY></TABLE><pre class="lia-code-sample language-abap"><code>METHOD migo_status_update. READ ENTITY IN LOCAL MODE zc_brt_po_head ALL FIELDS WITH VALUE # ( FOR ls_key IN keys ( ebeln = ls_key-ebeln ) ) RESULT DATA(lt_migo_status). LOOP AT lt_migo_status ASSIGNING FIELD-SYMBOL(&lt;fs_migo&gt;). IF &lt;fs_migo&gt;-porelease EQ abap_true. MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( migo_status ) WITH VALUE #( ( ebeln = &lt;fs_migo&gt;-ebeln migo_status = 'GR has done') ). ELSEIF &lt;fs_migo&gt;-porelease EQ abap_false. MODIFY ENTITY IN LOCAL MODE zc_brt_po_head UPDATE FIELDS ( migo_status ) WITH VALUE #( ( ebeln = &lt;fs_migo&gt;-ebeln migo_status = 'Open' ) ). ENDIF. ENDLOOP. ENDMETHOD. </code></pre><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Purpose--</STRONG></FONT></U></FONT></P><UL><LI><FONT face="times new roman,times"><SPAN>Whenever the field&nbsp;porelease&nbsp;is&nbsp;modified&nbsp;(via&nbsp;POREL,&nbsp;PONOREL, or&nbsp;Static_ALL), this determination triggers.</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>Updates&nbsp;migo_status&nbsp;dynamically:</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>'GR has done'&nbsp;→ if the PO is released (porelease&nbsp;=&nbsp;abap_true).</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>'Open'&nbsp;→ if the PO is not released (porelease&nbsp;=&nbsp;abap_false).</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><TABLE border="2"><TBODY><TR><TD><P><FONT face="times new roman,times"><STRONG><SPAN>Concept</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><STRONG><SPAN>Explanation</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD><P><FONT face="times new roman,times"><STRONG><SPAN>Determination</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>Runs automatically when a field changes (porelease) in RAP.</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD><P><FONT face="times new roman,times"><STRONG><SPAN>Local Mode</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>Updates the draft version, ensuring changes are visible in the UI before committing.</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD><P><FONT face="times new roman,times"><STRONG><SPAN>Dynamic Update</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>migo_status&nbsp;is computed automatically based on&nbsp;porelease.</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR><TR><TD><P><FONT face="times new roman,times"><STRONG><SPAN>No result table</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P></TD><TD><P><FONT face="times new roman,times"><SPAN>The UI will automatically get updated via RAP binding; no explicit&nbsp;result&nbsp;table&nbsp;needed.</SPAN><SPAN>&nbsp;</SPAN></FONT></P></TD></TR></TBODY></TABLE><P><STRONG><FONT face="times new roman,times"><SPAN class="">Create the service&nbsp;definition&nbsp;and service binding--</SPAN></FONT></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_4-1769664175553.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366691i0D3DE125AD7BF3F8/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_4-1769664175553.png" alt="Bikash_R_4-1769664175553.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_5-1769664184125.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366692iEB61478A7121F01A/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_5-1769664184125.png" alt="Bikash_R_5-1769664184125.png" /></span></P><P><STRONG><FONT face="times new roman,times"><SPAN class="">Let's&nbsp;preview our application in Fiori--</SPAN></FONT></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_6-1769664218575.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366693i16048C536E0F3508/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_6-1769664218575.png" alt="Bikash_R_6-1769664218575.png" /></span></P><P><FONT face="times new roman,times">Above&nbsp;can see the PO Release status and MIGO Status is done.&nbsp;</FONT></P><P><FONT face="times new roman,times">Let's&nbsp;create a record and see the&nbsp;pop-up.</FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_7-1769664248642.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366694iBDE1EB6765F89F76/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_7-1769664248642.png" alt="Bikash_R_7-1769664248642.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_8-1769664254933.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366695iE8568632EE200BDB/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_8-1769664254933.png" alt="Bikash_R_8-1769664254933.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_9-1769664276910.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366696i4DB59DBDA907B6E8/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_9-1769664276910.png" alt="Bikash_R_9-1769664276910.png" /></span></P><P><FONT face="times new roman,times">Above can the action button with drop down.&nbsp;</FONT></P><P><FONT face="times new roman,times">Let’s&nbsp;check the actions button, how PO release and MIGO status&nbsp;are changing.&nbsp;</FONT></P><P><FONT face="times new roman,times">Select one record--&gt;click on action drop-down--&gt;click on PO Not Release.</FONT>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_10-1769664304304.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366697i2DF2C4D81D783700/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_10-1769664304304.png" alt="Bikash_R_10-1769664304304.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_11-1769664311932.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/366698i43EE73C65937BD30/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_11-1769664311932.png" alt="Bikash_R_11-1769664311932.png" /></span></P><P><FONT face="times new roman,times"><SPAN class="">Now<SPAN>&nbsp;</SPAN>can see<SPAN>&nbsp;</SPAN>automatically MIGO status<SPAN>&nbsp;</SPAN>changed based on PO Release.</SPAN><SPAN class="">&nbsp;</SPAN></FONT></P><P><FONT size="4"><U><FONT face="times new roman,times"><STRONG>Conclusion--</STRONG></FONT></U></FONT></P><P><FONT face="times new roman,times">In this blog, we explored how to implement&nbsp;parameterized actions in RAP&nbsp;using&nbsp;abstract entities&nbsp;and a&nbsp;dropdown-based parameter&nbsp;selection, enabling flexible and user-driven behavior in Fiori applications.&nbsp;</FONT></P><P><FONT face="times new roman,times">We&nbsp;demonstrated&nbsp;how multiple actions -- such as POREL, PONOREL, and STATIC_ALL — can be designed to handle different business scenarios like&nbsp;Purchase Order release,&nbsp;mass update, and&nbsp;status refresh&nbsp;dynamically. Furthermore, with the MIGO_STATUS_UPDATE determination, we ensured&nbsp;real-time consistency&nbsp;between release and goods receipt statuses, illustrating the power of&nbsp;behavior-driven logic&nbsp;in the RAP framework.</FONT></P><P><FONT face="times new roman,times"><SPAN><SPAN class="">Thanks-------</SPAN><SPAN class="">&nbsp;</SPAN></SPAN></FONT></P> 2026-02-04T08:58:36.978000+01:00 https://community.sap.com/t5/technology-blog-posts-by-sap/triggering-sap-datasphere-bdc-task-chains-from-sap-btp-abap-cloud-using-the/ba-p/14325528 Triggering SAP Datasphere/BDC Task Chains from SAP BTP ABAP Cloud using the Task Chain REST API 2026-02-10T16:44:24.061000+01:00 stefan_geiselhart2 https://community.sap.com/t5/user/viewprofilepage/user-id/200897 <P>Our modern data landscapes thrive on automation. In this post, we’ll walk end-to-end through a real-life integration scenario that tackles one of the building blocks in this context:</P><P class="lia-align-center" style="text-align: center;"><STRONG>Starting a SAP Datasphere Task Chain remotely from SAP BTP ABAP Cloud using OAuth 2.0 Client Credentials and the Datasphere Task Chain REST API</STRONG></P><P>The goal is to orchestrate Datasphere data processing flows directly from ABAP Cloud — securely, programmatically, and fully automated.</P><P>We will cover the below points:</P><UL><LI>Creating a Task Chain in Datasphere</LI><LI>Configuring OAuth clients in Datasphere</LI><LI>Setting up Communication System &amp; Arrangement in ABAP Cloud</LI><LI>Executing the Task Chain remotely: Consume REST API from ABAP Cloud</LI></UL><P><FONT size="5"><STRONG>1 Architecture Overview</STRONG></FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Solution Architecture" style="width: 550px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371166iB8C9DA6C7F6550B3/image-dimensions/550x406?v=v2" width="550" height="406" role="button" title="image.png" alt="Solution Architecture" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Solution Architecture</span></span></P><P>ABAP Cloud&nbsp;Task Chain Execution: ABAP Cloud acts as the caller. Datasphere exposes the Task Chain API protected by OAuth.</P><P><FONT size="5"><STRONG>2 Prerequisites</STRONG></FONT></P><P>You must have:</P><UL><LI>SAP Datasphere tenant with developer + admin access</LI><LI>A Task Chain to trigger</LI><LI>SAP BTP ABAP Environment (ABAP Cloud) with developer access</LI><LI>BTP ABAP: Authorization to configure OAuth clients and Communication Arrangements</LI></UL><P><FONT size="5"><STRONG>3 Creating a Task Chain in SAP Datasphere</STRONG></FONT></P><P>The first step is defining a Task Chain that encapsulates the processing logic you want to execute remotely.</P><P>In the given example:</P><UL><LI>The Task Chain starts with a <STRONG>Begin</STRONG> node</LI><LI>Executes a <STRONG>Replication Flow</STRONG>&nbsp;for loading dimension data</LI><LI>(Can be extended with transformations, views, or further flows)</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="SAP Datasphere Task Chain with Replication Flow inside" style="width: 592px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371084i85FF39979A8A1F3B/image-dimensions/592x320?v=v2" width="592" height="320" role="button" title="image.png" alt="SAP Datasphere Task Chain with Replication Flow inside" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">SAP Datasphere Task Chain with Replication Flow inside</span></span></P><P><EM>Main takeaways:</EM></P><UL><LI>Task Chain must be <EM>Deployed</EM></LI><LI>Note the <EM>Technical Name</EM> (used later by API)</LI><LI>Verify it runs manually before you automate via the API<STRONG>&nbsp;</STRONG></LI></UL><P><FONT size="5"><STRONG>4 Configuring OAuth Client in SAP Datasphere</STRONG></FONT></P><P>To allow ABAP Cloud to call Datasphere APIs securely, we create an OAuth Client in Datasphere Administration.</P><P><EM>Navigation Path</EM></P><P>Datasphere → Administration → App Integration → OAuth Clients</P><P><EM>OAuth Endpoints Provided</EM></P><P>Amongst others, SAP Datasphere automatically exposes:</P><UL><LI>Authorization URL</LI><LI>Token URL</LI></UL><P>These are required for OAuth2 token retrieval. Moreover you must create a technical user that has access to the Datasphere space and is able to run the task chains that are in scope. Typically this is done by assigning a scoped role.</P><P><EM>Configured OAuth Client (based on Technical User)</EM></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Menu Path Datasphere" style="width: 172px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371014i26654901577A6E67/image-size/large?v=v2&amp;px=999" role="button" title="image.png" alt="Menu Path Datasphere" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Menu Path Datasphere</span></span></STRONG></P><P>This is where you see the OAuth Client specific URLs - take note of them for later configuration in ABAP BTP:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="OAuth Client Generation" style="width: 764px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371054i4BB7492B30B71B30/image-dimensions/764x458?v=v2" width="764" height="458" role="button" title="image.png" alt="OAuth Client Generation" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">OAuth Client Generation</span></span></P><P>Your specific OAuth client for consumption from ABAP BTP. The secret key is only shown once upon creation - keep this in mind!</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="OAuth Client Details" style="width: 404px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371055i19C15B5494614179/image-dimensions/404x580?v=v2" width="404" height="580" role="button" title="image.png" alt="OAuth Client Details" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">OAuth Client Details</span></span></P><P><EM>Important settings:</EM></P><TABLE><TBODY><TR><TD><P><STRONG>Parameter</STRONG></P></TD><TD><P><STRONG>Value</STRONG></P></TD></TR><TR><TD><P>Grant Type</P></TD><TD><P>Client Credentials</P></TD></TR><TR><TD><P>Purpose</P></TD><TD><P>Technical User</P></TD></TR><TR><TD><P>Roles</P></TD><TD><P>space access must be given (e.g. by scope role in DSP)</P></TD></TR><TR><TD><P>Token Lifetime</P></TD><TD><P>e.g. 60 minutes</P></TD></TR></TBODY></TABLE><P>Save the <EM>Client ID</EM> and <EM>Client Secret </EM>— this is used in ABAP Cloud later on.</P><P><FONT size="5"><STRONG>&nbsp;5&nbsp;</STRONG><STRONG>Creating Communication Artifacts in ABAP Cloud</STRONG></FONT></P><P>Now we configure the outbound technical connection from ABAP Cloud to Datasphere.</P><P>First create an Outbound Service of type HTTP:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Create Outbound Service" style="width: 498px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371664i6B7CF4506456A6F6/image-dimensions/498x184?v=v2" width="498" height="184" role="button" title="image.png" alt="Create Outbound Service" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Create Outbound Service</span></span></P><P>Create a Communication Scenario with Authentication Methods = OAuth 2.0 only, bind it to your outbound service and publish it:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Communication Scenario Creation" style="width: 618px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371665iF1366B36E6FF0402/image-dimensions/618x251?v=v2" width="618" height="251" role="button" title="image.png" alt="Communication Scenario Creation" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Communication Scenario Creation</span></span></P><P><EM>Navigation:&nbsp;</EM>ABAP Environment Web Access → Communication Management → Communication Systems</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ABAP Cloud Web Access" style="width: 671px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371057i5B672EC77D24D22E/image-dimensions/671x269?v=v2" width="671" height="269" role="button" title="image.png" alt="ABAP Cloud Web Access" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Cloud Web Access</span></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ABAP Cloud Communication Systems" style="width: 672px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371058i1807DF17EA76120F/image-dimensions/672x113?v=v2" width="672" height="113" role="button" title="image.png" alt="ABAP Cloud Communication Systems" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Cloud Communication Systems</span></span></P><P>The hostname is your Datasphere tenant URL. Outbound OAuth URLs (like Token/Authentication) can be found on the Datasphere side under Administration -&gt; App Integration (previous step).</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ABAP Cloud Communication Systems Details" style="width: 673px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371059iF14B49A880B877F1/image-dimensions/673x497?v=v2" width="673" height="497" role="button" title="image.png" alt="ABAP Cloud Communication Systems Details" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Cloud Communication Systems Details</span></span></P><P>You have to add a user "OAuth 2.0 (Basic)":</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ABAP Cloud Communication Systems Users" style="width: 672px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371061i0EC89B23ACC3A7F5/image-dimensions/672x269?v=v2" width="672" height="269" role="button" title="image.png" alt="ABAP Cloud Communication Systems Users" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Cloud Communication Systems Users</span></span></P><P><EM>Key fields:</EM></P><TABLE><TBODY><TR><TD><P><EM>Field</EM></P></TD><TD><P><EM>Example</EM></P></TD></TR><TR><TD><P>System ID</P></TD><TD><P>DSP_REST</P></TD></TR><TR><TD><P>Host Name</P></TD><TD><P>&lt;your-datasphere-host&gt; (tenant URL)</P></TD></TR><TR><TD><P>Port</P></TD><TD><P>443</P></TD></TR><TR><TD><P>OAuth 2.0 Endpoints</P></TD><TD><P>From Datasphere for Token &amp; Authorization URL (Audience URL not required)</P></TD></TR><TR><TD><P>Client ID</P></TD><TD><P>Datasphere OAuth Client ID</P></TD></TR><TR><TD><P>Client Secret</P></TD><TD><P>Datasphere Secret (you must take note of this when creating the OAuth Client)</P></TD></TR></TBODY></TABLE><P><FONT size="5"><STRONG>6 Creating a Communication Arrangement in SAP ABAP Cloud</STRONG></FONT></P><P>Now we bind the Communication System to a Communication Scenario that allows REST calls.</P><P><EM>Navigation:&nbsp;</EM>Communication Management → Communication Arrangements</P><P><EM>Arrangement Example: ZDSP_CS_REST</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ABAP Cloud Communication Arrangements" style="width: 675px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371062i5D6E57F823E5F6EB/image-dimensions/675x138?v=v2" width="675" height="138" role="button" title="image.png" alt="ABAP Cloud Communication Arrangements" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Cloud Communication Arrangements</span></span></P><P>Note the service path: The dynamic parts of the path are set from ABAP (this is to keep the space + task chain flexible and controllable from the actual caller: ABAP).</P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ABAP Cloud Communication Arrangements Detailed Configuration" style="width: 673px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371063i82A3F766212E7AA8/image-dimensions/673x334?v=v2" width="673" height="334" role="button" title="image.png" alt="ABAP Cloud Communication Arrangements Detailed Configuration" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Cloud Communication Arrangements Detailed Configuration</span></span></EM></P><P><EM>What this provides:</EM></P><UL><LI>Preconfigured service URL</LI><LI>OAuth token handling by ABAP runtime</LI><LI>Secure outbound API consumption</LI></UL><P><FONT size="5"><STRONG>7 Calling the Datasphere Task Chain API from ABAP Cloud</STRONG></FONT></P><P>Now comes the fun part: consuming the REST API. Datasphere exposes endpoints such as:</P><UL><LI>POST /api/v1/datasphere/tasks/chains/&lt;space_id&gt;/run/&lt;task_chain_technical_name&gt;</LI><LI>GET&nbsp;/api/v1/datasphere/tasks/logs/&lt;space_id&gt;/&lt;log_id&gt;</LI></UL><P>Which triggers a new execution or reads the status of a task chain run.</P><P><EM>ABAP Cloud Implementation Pattern</EM></P><P>In ABAP Cloud when working with REST API to integrate external services, you typically:</P><OL><LI>Create HTTP destination automatically from the created Communication Arrangement</LI><LI>Use CL_WEB_HTTP_CLIENT_MANAGER</LI><LI>Perform POST/GET requests</LI><LI>Parse response (run ID, status)</LI></OL><P>The code snippet performs the following parts in more detail:</P><OL><LI><EM>Run as a class-run program</EM> (IF_OO_ADT_CLASSRUN) -&gt; you can execute directly from ADT and print to the console.</LI><LI><EM>Locate the configured Communication Arrangement</EM> (bound to our Communication System DSP_REST) using CL_COM_ARRANGEMENT_FACTORY.</LI><LI><EM>Create an HTTP destination</EM> from the Communication Arrangement using CL_HTTP_DESTINATION_PROVIDER=&gt;CREATE_BY_COMM_ARRANGEMENT.</LI><LI><EM>Create an HTTP client</EM> from the destination (CL_WEB_HTTP_CLIENT_MANAGER).</LI><LI><EM>POST</EM>&nbsp;request to the Task Chain “run” endpoint:</LI><UL><LI>triggers a new run</LI><LI>receives a JSON response containing a <EM>LogId</EM></LI></UL><LI><EM>WAIT</EM> a few seconds.</LI><LI><EM>GET</EM> the log endpoint using the returned&nbsp;<EM>LogId</EM>:</LI><UL><LI>retrieves the execution status (RUNNING, later SUCCESS / FAILED, etc.)</LI></UL><LI>Print everything in the <EM>ABAP Console</EM>.</LI></OL><P>ABAP-Code Snippet:</P><pre class="lia-code-sample language-abap"><code>CLASS zcl_dsp_rest_api DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES if_oo_adt_classrun. CLASS-DATA: out TYPE REF TO if_oo_adt_classrun_out. CLASS-METHODS: call_dsp RAISING cx_http_dest_provider_error cx_web_http_client_error. ENDCLASS. CLASS zcl_dsp_rest_api IMPLEMENTATION. METHOD if_oo_adt_classrun~main. zcl_dsp_rest_api=&gt;out = out. TRY. call_dsp( ). CATCH cx_web_http_client_error cx_http_dest_provider_error INTO DATA(exception). out-&gt;write( exception-&gt;get_text( ) ). ENDTRY. ENDMETHOD. METHOD call_dsp. TYPES: BEGIN OF ty_log, logId TYPE i, END OF ty_log. DATA: ls_log TYPE ty_log. DATA(communication_system) = 'DSP_REST'. DATA(arrangement_factory) = cl_com_arrangement_factory=&gt;create_instance( ). DATA(comm_arrangement_range) = VALUE if_com_arrangement_factory=&gt;ty_query-cs_id_range( ( sign = 'I' option = 'EQ' low = communication_system ) ). arrangement_factory-&gt;query_ca( EXPORTING is_query = VALUE #( cs_id_range = comm_arrangement_range ) IMPORTING et_com_arrangement = DATA(arrangements) ). DATA(arrangement) = arrangements[ 1 ]. DATA(destination) = cl_http_destination_provider=&gt;create_by_comm_arrangement( comm_scenario = 'ZDSP_CS_REST' service_id = 'ZDSP_REST_SRV_REST' comm_system_id = arrangement-&gt;get_comm_system_id( ) ). DATA(http_client) = cl_web_http_client_manager=&gt;create_by_http_destination( destination ). DATA(request) = http_client-&gt;get_http_request( ). request-&gt;set_uri_path( '/chains/BDCPOC/run/TC_DIM2_A001' ). DATA(response) = http_client-&gt;execute( if_web_http_client=&gt;post ). CALL METHOD /ui2/cl_json=&gt;deserialize EXPORTING json = response-&gt;get_text( ) CHANGING data = ls_log. data(log_str) = CONV string( ls_log-logId ). out-&gt;write( 'Task Chain started. LogId created:' &amp;&amp; log_str ). WAIT UP TO 10 SECONDS. CONCATENATE '/logs/BDCPOC/' log_str INTO DATA(uri). clear: request, response, http_client. http_client = cl_web_http_client_manager=&gt;create_by_http_destination( destination ). request = http_client-&gt;get_http_request( ). request-&gt;set_uri_path( uri ). response = http_client-&gt;execute( if_web_http_client=&gt;get ). out-&gt;write( 'Task Chain Log REST API - via GET - Task Chain Status:' &amp;&amp; response-&gt;get_text( ) ). ENDMETHOD. ENDCLASS.</code></pre><P>Once triggered:</P><UL><LI>Datasphere creates a new Task Chain run</LI><LI>Execution can be monitored in Datasphere UI</LI><LI>API returns run ID and status</LI></UL><P>Follow-up calls can fetch:</P><UL><LI>Execution status</LI><LI>Logs</LI><LI>Completion result</LI></UL><P><FONT size="5"><STRONG>8 Execution Results</STRONG></FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ABAP Cloud Console Log: Results" style="width: 964px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371044iA43931A0457AB770/image-size/large?v=v2&amp;px=999" role="button" title="image.png" alt="ABAP Cloud Console Log: Results" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Cloud Console Log: Results</span></span></P><P>The Task Chain in Datasphere is in Running status:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="SAP Datasphere Task Chain Running Status" style="width: 871px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371046i89C5349410537884/image-size/large?v=v2&amp;px=999" role="button" title="image.png" alt="SAP Datasphere Task Chain Running Status" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">SAP Datasphere Task Chain Running Status</span></span></P><P><FONT size="5"><STRONG>9 Conclusion/Outlook &amp; Further aspects:</STRONG></FONT></P><P><STRONG>Overview of the major building blocks:</STRONG></P><TABLE><TBODY><TR><TD><P><STRONG>Capability</STRONG></P></TD><TD><P><STRONG>Result</STRONG></P></TD></TR><TR><TD><P>Secure Auth</P></TD><TD><P>OAuth 2.0 Client Credentials</P></TD></TR><TR><TD><P>No hardcoded secrets</P></TD><TD><P>via Communication Arrangements/System</P></TD></TR><TR><TD><P>Remote orchestration</P></TD><TD><P>Creating an end-to-end orchestrated chain of tasks</P></TD></TR><TR><TD><P>Cloud-native ABAP</P></TD><TD><P>Using appropriate ABAP Class APIs</P></TD></TR><TR><TD><P>Datasphere automation</P></TD><TD><P>Using Task Chain API</P></TD></TR></TBODY></TABLE><P><STRONG>Use Cases that the implementation enables:</STRONG></P><UL><LI>Nightly batch orchestration</LI><LI>Event-driven data loads</LI><LI>Cross-system workflows (this was our ultimate focus)</LI><LI>CI/CD data pipelines</LI><LI>API-driven analytical data refresh</LI></UL><P><STRONG>References</STRONG></P><UL><LI><SPAN>SAP Datasphere Task Chain API Documentation: </SPAN><A href="https://api.sap.com/api/DatasphereTasks/overview" target="_blank" rel="noopener noreferrer"><SPAN>https://api.sap.com/api/DatasphereTasks/overview</SPAN></A></LI><LI><SPAN>SAP Datasphere Task Chain Help Page: </SPAN><A href="https://help.sap.com/docs/SAP_DATASPHERE/c8a54ee704e94e15926551293243fd1d/274f2736465c4c48a091c675880502a2.html?locale=en-US" target="_blank" rel="noopener noreferrer"><SPAN>https://help.sap.com/docs/SAP_DATASPHERE/c8a54ee704e94e15926551293243fd1d/274f2736465c4c48a091c675880502a2.html?locale=en-US</SPAN></A></LI><LI><SPAN>ABAP Cloud - how to call external APIs: </SPAN><A href="https://jacekw.dev/blog/2022/oauth-client-credentials-from-abap-cloud/" target="_blank" rel="noopener nofollow noreferrer"><SPAN>https://jacekw.dev/blog/2022/oauth-client-credentials-from-abap-cloud/</SPAN></A></LI></UL><P><STRONG>These are your main takeaways to further <U>sharpen</U> the solution:</STRONG></P><UL><LI>Use short token lifetimes</LI><LI>Separate technical OAuth users</LI><LI>Monitor task runs via API from ABAP</LI><LI>Handle retries &amp; failures in ABAP</LI><LI>Log run IDs for observability</LI></UL><P>If you have any aspects, comments and/or concerns, please raise them and let's discuss. I'm happy and proud that this article was written by at least 90% human and only 10% AI <span class="lia-unicode-emoji" title=":slightly_smiling_face:">🙂</span></P> 2026-02-10T16:44:24.061000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/unlock-s-4hana-cloud-secrets-hybrid-events-apis-strategy-for-seamless-btp/ba-p/14326758 Unlock S/4HANA Cloud Secrets: Hybrid Events+APIs Strategy for Seamless BTP Data Flows 2026-02-12T01:30:35.487000+01:00 tamitdassharma https://community.sap.com/t5/user/viewprofilepage/user-id/153763 <H2 id="toc-hId-1789646278">Strategic Financial Data Extraction from SAP S/4HANA Cloud Public Edition to SAP BTP</H2><H4 id="toc-hId-1851298211">Using Transfer Pricing as a Real-World Example</H4><P>Transfer pricing represents a perfect use case to demonstrate <STRONG>generic financial data extraction strategies</STRONG> from SAP S/4HANA Cloud Public Edition. Multinational organisations need GL, Controlling, Material Ledger, and Asset Accounting postings to flow reliably to external engines hosted on SAP BTP—but Public Cloud’s “no direct database access” constraint demands architecturally sound patterns.</P><H3 id="toc-hId-1525701987">Why Transfer Pricing Perfectly Illustrates the Challenge</H3><P><STRONG>The business need</STRONG>: Calculate inter-company markups (cost-plus, resale-minus) using real-time ACDOCA postings across multiple currencies, profit centres, and cost elements.<BR /><STRONG>The constraint</STRONG>: Pure cloud extensibility—no RFCs, no custom ABAP, no direct table extracts.&nbsp;<BR /><STRONG>The solution:</STRONG> Three proven patterns that work for any financial data integration scenario.</P><H3 id="toc-hId-1329188482">Pattern 1: Event Notifications (Real-Time Push Model)</H3><P><STRONG>How transfer pricing uses it</STRONG>: GL postings trigger automatic business event notifications routed through SAP Event Mesh to BTP applications.</P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Event Notification" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371720i4CB6FC368836A2D3/image-size/large?v=v2&amp;px=999" role="button" title=" - visual selection-3.png" alt="Event Notification" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Event Notification</span></span></P><P><SPAN><STRONG>Generic applicability</STRONG>: Works for any posting-driven process—revenue recognition, inter-company reconciliation, compliance monitoring.&nbsp;</SPAN></P><DIV><STRONG>High-level activation</STRONG>:</DIV><OL><LI><SPAN><STRONG>Integration configuration apps</STRONG> → Activate accounting-related event notifications</SPAN></LI><LI><SPAN><STRONG>Communication scenarios</STRONG> → Configure outbound event destinations</SPAN></LI><LI><SPAN><STRONG>Event Mesh subscription</STRONG> → Point to BTP service endpoint</SPAN></LI><LI><SPAN><STRONG>Payload contains</STRONG>: Company codes, ledger amounts (local/group), profit centres, material valuations</SPAN></LI></OL><H3 id="toc-hId-1132674977">Pattern 2: Standard Query Services (Scheduled Pull Model)</H3><P><STRONG>How transfer pricing uses it</STRONG>: BTP service queries S/4HANA nightly for new/changed financial postings.</P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Query Service" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371722iBABF11B5D5404615/image-size/large?v=v2&amp;px=999" role="button" title=" - visual selection-4.png" alt="Query Service" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Query Service</span></span><STRONG><SPAN>Key services (release-dependent availability):</SPAN></STRONG></P><UL><LI><SPAN><STRONG>Financial line item services</STRONG> → GL/CO/ML/AA postings</SPAN></LI><LI><SPAN><STRONG>Profitability services</STRONG> → Margin analysis data</SPAN></LI><LI><SPAN><STRONG>Material valuation services</STRONG> → Cost component details</SPAN></LI></UL><P><STRONG>Generic applicability</STRONG>: Perfect for scheduled reconciliation, historical backfills, or validation runs.</P><H3 id="toc-hId-936161472">Pattern 3: Hybrid Extraction (Production Resilience)</H3><P>Transfer pricing demands 99.9% coverage. Smart architects layer all three patterns:</P><TABLE border="1" width="100%"><TBODY><TR><TD width="25%"><STRONG>Use Case</STRONG></TD><TD width="25%"><STRONG>Primary Pattern</STRONG></TD><TD width="25%"><STRONG>Transfer Pricing Example</STRONG></TD><TD width="25%"><STRONG>Generic Use</STRONG></TD></TR><TR><TD width="25%">Real-time GL postings</TD><TD width="25%">Event notifications</TD><TD width="25%">Invoice → immediate markup</TD><TD width="25%">Any posting trigger</TD></TR><TR><TD>Historical catch-up</TD><TD>Standard APIs</TD><TD>Month-end reconciliation</TD><TD>Data migration</TD></TR><TR><TD>Day 1 implementation</TD><TD>Bulk extraction</TD><TD>Full ACDOCA baseline</TD><TD>Initial loads</TD></TR><TR><TD>Custom calculations</TD><TD>BTP processing</TD><TD>Exception overrides</TD><TD>Business rules</TD></TR></TBODY></TABLE><P><STRONG>&nbsp;Three-tier reference flow:</STRONG></P><H4 id="toc-hId-868730686"><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Hybrid Extraction" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371723i0FA6EF631F99C2FE/image-size/large?v=v2&amp;px=999" role="button" title=" - visual selection-5.png" alt="Hybrid Extraction" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Hybrid Extraction</span></span></STRONG><SPAN>BTP Implementation Patterns (Transfer Pricing Example)</SPAN></H4><H5 id="toc-hId-801299900"><SPAN>Cloud Application Programming Model (CAP)</SPAN></H5><pre class="lia-code-sample language-javascript"><code>service FinancialIntegration { entity Postings as projection on external financial services; entity PricingResults as projection on HANA staging; }</code></pre><P><SPAN><STRONG>&nbsp;Pattern</STRONG>: Event handlers + scheduled queries → unified HANA staging → business rules.</SPAN></P><H5 id="toc-hId-604786395"><SPAN>ABAP RESTful Application Programming (RAP)</SPAN></H5><pre class="lia-code-sample language-abap"><code>define root view entity FinancialDataView as select from standard financial services</code></pre><P><STRONG>Pattern</STRONG>: Analytical CDS views over external data → transactional services.</P><H4 id="toc-hId-279190171">Architect’s Production Checklist</H4><P><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Tenant validation: Test events/APIs in your specific S/4HANA Cloud environment<BR /><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Quota management: Monitor Event Mesh throughput + API rate limits<BR /><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Fallback design: API polling validates event stream completeness<BR /><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Quarterly readiness: SAP evolves event coverage and API fields continuously<BR /><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Pure cloud: Zero custom code in production S/4HANA</P><H4 id="toc-hId--415040429">The Universal Pattern</H4><DIV>Transfer pricing proves the strategy works for complex financial scenarios. The same architecture applies to:</DIV><UL><LI><SPAN>Inter-company reconciliation</SPAN></LI><LI><SPAN>Revenue recognition automation</SPAN></LI><LI><SPAN>Compliance reporting engines</SPAN></LI><LI><SPAN>Analytics data pipelines</SPAN></LI><LI><SPAN>Any standard data object/model driven process</SPAN></LI></UL><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Universal Pattern" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371724i43222D4AB9F30955/image-size/large?v=v2&amp;px=999" role="button" title=" - visual selection-6.png" alt="Universal Pattern" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Universal Pattern</span></span></SPAN><SPAN><STRONG>Key takeaway</STRONG>: This isn’t “just for transfer pricing”—it’s your reusable blueprint for any S/4HANA Cloud → BTP data integration.&nbsp;</SPAN></P> 2026-02-12T01:30:35.487000+01:00 https://community.sap.com/t5/abap-blog-posts/recurring-entry-approval-workflow-in-sap-s-4hana-fbd1-fbd2-fbd9/ba-p/14333536 Recurring Entry Approval Workflow in SAP S/4HANA - FBD1/FBD2/FBD9 Transactions 2026-02-24T08:51:32.650000+01:00 ShravanBalaji16897 https://community.sap.com/t5/user/viewprofilepage/user-id/2283030 <P><STRONG>Introduction:</STRONG></P><P>In many organizations, finance teams handle repetitive postings such as rent, subscriptions, insurance, lease payments, and service charges. Manually posting these entries every period increases operational effort and the risk of errors.</P><P>SAP provides the <STRONG>Recurring Entry Program (Transaction FBD1)</STRONG> to automate such postings. However, in controlled environments, organizations often require <STRONG>approval workflows</STRONG> before recurring documents are posted.</P><P>This blog explains how to implement and control a <STRONG>Recurring Entry Workflow using FBD1</STRONG>, ensuring automation with proper financial governance.</P><P><STRONG>Requirement:</STRONG></P><P>In SAP Standard, through <STRONG>FBD1 </STRONG>users can create recurring document templates. But these templates cannot be posted automatically. The created recurring document templates must be posted via <STRONG>F.14</STRONG> transaction. It happens periodically through Job Scheduling.</P><P><STRONG>FBD1 </STRONG>does not include any approval mechanism by standard. This leads to</P><UL><LI>Unauthorized financial commitments.</LI><LI>Incorrect Recurring Postings.</LI><LI>Audit, Compliance &amp; Seggregation of Duties (SoD) violations.</LI></UL><P>To mitigate these risks, business requires an approval mechanism, so that</P><UL><LI>Authorized user only creates Recurring Document Templates (FBD1).</LI><LI>Delegation of Authority (DoA) ensures proper screening before approval.</LI><LI>Approved entries alone will be considered for Posting Runs.</LI></UL><P><STRONG>Solution Architecture:</STRONG></P><P>The proposed solution will work on triggering an approval workflow when the user <STRONG>creates a Recurring Document Entry through FBD1 </STRONG>and when he <STRONG>modifies the</STRONG> <STRONG>rejected Recurring Document Entry through FBD2. </STRONG>Modifications of the Recurring Document Template when it is in Approval is prevented through Custom Control Error Mechanism.</P><P><STRONG>Process Flow:</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_0-1771764079437.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375116iCC04AF1BD543880E/image-size/medium?v=v2&amp;px=400" role="button" title="ShravanBalaji16897_0-1771764079437.png" alt="ShravanBalaji16897_0-1771764079437.png" /></span></P><P><STRONG>Development Process:</STRONG></P><P><STRONG>Step – 1: </STRONG>Create a Recurring Document Entry Template in FBD1 T-Code. The Entry must be blocked, so that only upon complete approval of workflow block shall be removed and would process for posting.</P><P>For this purpose, we must enhance the standard procedure through Business Transaction Events. To identify the suitable BTE’s that can be used for our purpose, we can use SE37 transaction with the FM “<STRONG>PC_FUNCTION_FIND”. </STRONG>Keep a Session Breakpoint in the FM and run the process. The Parameter “<STRONG>I_EVENT” </STRONG>will provide the BTE numbers from which we can choose the suitable one for our purpose.</P><P><STRONG>NOTE: For Blocking the Document while creation, through the above-mentioned process we came to the BTE as “SAMPLE_INTERFACE_00001025”.</STRONG></P><P><STRONG>Step – 2:</STRONG> Take a copy of the FM “SAMPLE_INTERFACE_00001025” in SE37. I have kept the name as “ZFI_BKDF_DOC_BLOCK_FM”.</P><P>Copy and paste the below code inside the FM.</P><pre class="lia-code-sample language-abap"><code>DATA: lv_memory_bkdf TYPE char30 VALUE '(SAPMF05A)BKDF', lv_memory_bkdf1 TYPE char30 VALUE '(SAPMF05L)BKDF', wa_bkpf TYPE bkpf. FIELD-SYMBOLS: &lt;lfs_bkdf&gt; TYPE bkdf. READ TABLE t_bkpf into wa_bkpf index 1. If sy-tcode = 'FBD1' or sy-tcode = 'FBD9'. ASSIGN (lv_memory_bkdf) TO &lt;lfs_bkdf&gt;. elseif sy-tcode = 'FBD2'. ASSIGN (lv_memory_bkdf1) TO &lt;lfs_bkdf&gt;. endif. IF &lt;lfs_bkdf&gt; IS ASSIGNED AND t_bkpf-bukrs EQ '9000'. &lt;lfs_bkdf&gt;-blocked_for_posting = abap_true. &lt;lfs_bkdf&gt;-XDELT = abap_true. ENDIF.</code></pre><P><STRONG>NOTE: </STRONG></P><UL><LI><STRONG>Here “BLOCKED_FOR_POSTING” &amp; “XDELT (Deletion_Indicator) are the fields for which value has been to “X” for blocking the document. </STRONG></LI><LI><STRONG>The runtime values of these fields are fetched from previous procedures through Memory Assignment. </STRONG></LI></UL><P><STRONG>For FBD1 &amp; FBD2, the standard procedural program varies (See Data Declaration).</STRONG></P><P><STRONG>Step – 3: </STRONG>Once the Recurring Entry Document is blocked and saved, our custom workflow must get triggered. Before proceeding to Workflow, we must create a custom class where the Event, Methods necessary for the workflow operation would reside.</P><OL><LI>Go to the T-code SE24 and create a custom class. I had created in the name “ZCL_FI_RECURRING_WF”. <STRONG>&nbsp;</STRONG>In the <STRONG>Interfaces</STRONG> tab, provide the interfaces as shown in the below image. These interfaces are necessary for Object instantiation &amp; Workflow Operations.<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_1-1771764158227.png" style="width: 595px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375117i3C89B658F7429318/image-dimensions/595x128?v=v2" width="595" height="128" role="button" title="ShravanBalaji16897_1-1771764158227.png" alt="ShravanBalaji16897_1-1771764158227.png" /></span></LI><LI>In the <STRONG>Events</STRONG> Tab, I have given the event name as <STRONG>“CREATED” </STRONG>as shown below.<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_2-1771764196254.png" style="width: 584px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375118i38EA160993DF5D9C/image-dimensions/584x98?v=v2" width="584" height="98" role="button" title="ShravanBalaji16897_2-1771764196254.png" alt="ShravanBalaji16897_2-1771764196254.png" /></span><STRONG><BR />The event parameter is “ZST_WF_REC_JOUR”. It is a custom table type referring a custom structure "</STRONG> <STRONG>ZFI_ST_RECJOUR_ENTRY”.</STRONG><BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_3-1771764228387.png" style="width: 585px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375119iAE31777700BC375E/image-dimensions/585x66?v=v2" width="585" height="66" role="button" title="ShravanBalaji16897_3-1771764228387.png" alt="ShravanBalaji16897_3-1771764228387.png" /></span><STRONG><STRONG><BR />Structure:<BR /></STRONG></STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_4-1771764298827.png" style="width: 570px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375120iBF7079611774C05F/image-dimensions/570x193?v=v2" width="570" height="193" role="button" title="ShravanBalaji16897_4-1771764298827.png" alt="ShravanBalaji16897_4-1771764298827.png" /></span></LI><LI>In the<STRONG> Attributes </STRONG>tab, Object Key is specified as “LV_OBJKEY” as shown below.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_5-1771764330729.png" style="width: 566px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375121iBD6F802DC9A58A09/image-dimensions/566x53?v=v2" width="566" height="53" role="button" title="ShravanBalaji16897_5-1771764330729.png" alt="ShravanBalaji16897_5-1771764330729.png" /></span></LI><LI>The standard methods corresponding to the added interfaces, would reflect in the <STRONG>Methods</STRONG> tab as shown below.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_6-1771764365495.png" style="width: 565px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375122i77AB3FAF2E62F1C0/image-dimensions/565x120?v=v2" width="565" height="120" role="button" title="ShravanBalaji16897_6-1771764365495.png" alt="ShravanBalaji16897_6-1771764365495.png" /></span></LI><LI>Now we can add our custom methods. The following are the methods that I created for my requirement as shown below.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_7-1771764399519.png" style="width: 569px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375123i539100101E5A7568/image-dimensions/569x37?v=v2" width="569" height="37" role="button" title="ShravanBalaji16897_7-1771764399519.png" alt="ShravanBalaji16897_7-1771764399519.png" /></span><STRONG>M_FETCH_APPROVER – Fetching Approvers and Sending Approval Notifications.</STRONG><BR /><STRONG>M_UNBLOCK_POSTING – Unblocking the Recurring Entry Document after Complete Approval.</STRONG><BR /><STRONG>M_COMPLETE_MAIL – Notification Mail to Initiator after Complete Approval / Rejection in any level.</STRONG></LI><LI>The individual method procedures and its parameters are below.<BR /><STRONG>M_FETCH_APPROVER:</STRONG><BR /><STRONG>Parameters:</STRONG><BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_8-1771764476179.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375124i20740161E6D6161B/image-size/medium?v=v2&amp;px=400" role="button" title="ShravanBalaji16897_8-1771764476179.png" alt="ShravanBalaji16897_8-1771764476179.png" /></span><BR /><STRONG><STRONG>Here, “ZTT_FI_WF_AGENT” table type is a single field for storing the agents (Image represents structure of the Table Type).<BR /></STRONG></STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_9-1771764508727.png" style="width: 559px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375125i00804A41FFB90DBE/image-dimensions/559x151?v=v2" width="559" height="151" role="button" title="ShravanBalaji16897_9-1771764508727.png" alt="ShravanBalaji16897_9-1771764508727.png" /></span><STRONG>&nbsp;“ZFI_RECUR_MAT_APP_TT” table type is for storing agent information (Image represents structure of the Table Type).</STRONG><BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_10-1771764553919.png" style="width: 551px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375126i56C24316059FC932/image-dimensions/551x197?v=v2" width="551" height="197" role="button" title="ShravanBalaji16897_10-1771764553919.png" alt="ShravanBalaji16897_10-1771764553919.png" /></span></LI></OL><pre class="lia-code-sample language-abap"><code>DATA: gc_subject TYPE so_obj_des, " Email subject gc_email_to TYPE adr6-smtp_addr, " Valid email gs_text TYPE soli, " Text used into the email body gc_type_raw TYPE so_obj_tp, " Email type gc_att_type TYPE soodk-objtp, " Attachment type gc_att_subject TYPE sood-objdes. " Attachment title DATA: gt_text TYPE soli_tab, " Table which contains email body text gt_attachment_hex TYPE solix_tab, " Table which contains the attached file gv_sent_to_all TYPE os_boolean, " Receive the information if email was sent gv_error_message TYPE string, " Used to get the error message go_send_request TYPE REF TO cl_bcs, " Email object go_recipient TYPE REF TO if_recipient_bcs, " Who will receive the email go_sender TYPE REF TO cl_sapuser_bcs, " Who is sending the email go_document TYPE REF TO cl_document_bcs, " Email body gx_bcs_exception TYPE REF TO cx_bcs, wa_agents type ZST_FI_APPWF_AGENT. wa_rec_wf_sts type ZFI_REC_WF_ST_DT. lv_initiator = lv_initiator_us+2(12). lv_counter = lv_counter + 1. CALL METHOD zcl_amdp_fi_recurring_wf=&gt;get_initial_approvers EXPORTING p_mandt = sy-mandt p_compcode = lv_comp_code p_init = lv_initiator IMPORTING it_approvers = data(it_approvers). sort it_approvers by zlevel . delete ADJACENT DUPLICATES FROM it_approvers comparing zlevel. DESCRIBE TABLE it_approvers LINES lv_counter_max. read table it_approvers into data(wa_approver) index 1. if sy-subrc = 0. lv_init_name = wa_approver-name_text1. lv_init_mid = wa_approver-smtp_addr1. endif. read table it_approvers into wa_approver with key zlevel = lv_counter. if sy-subrc = 0. concatenate 'US' wa_approver-zuser into wa_agents-agent. lv_appr_mid = wa_approver-smtp_addr. lv_appr_name = wa_approver-name_text. append wa_agents to it_agents. endif. TRY. go_send_request = cl_bcs=&gt;create_persistent( ). go_sender = cl_sapuser_bcs=&gt;create( 'SAP_WFRT' ). go_send_request-&gt;set_sender( i_sender = go_sender ). DATA(lv_belnr1) = lv_belnr. SHIFT lv_belnr1 LEFT DELETING LEADING '0'. CONCATENATE 'Approve Jounral Entry' lv_comp_code '-' lv_belnr1 '-' lv_gjahr INTO gc_subject SEPARATED BY space. gs_text-line = '&lt;HTML&gt;&lt;BODY&gt;'. APPEND gs_text to gt_text[]. CLEAR: gs_text. concatenate 'Dear' lv_appr_name into gs_text-line SEPARATED BY SPACE. APPEND gs_text TO gt_text[]. CLEAR : gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. concatenate 'Recurring Journal Entry' lv_belnr1 '-' lv_comp_code '-' lv_gjahr 'is waiting for your approval.' into gs_text-line separated by space . APPEND gs_text TO gt_text[]. CLEAR : gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = 'Please review the details using the provided link.'. APPEND gs_text TO gt_text[]. CLEAR : gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = 'This is a system generated mail. Please do not reply to this.'. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = 'Thanks and Regards,'. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = lv_init_name. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;/HTML&gt;&lt;/BODY&gt;'. APPEND gs_text to gt_text[]. CLEAR: gs_text. go_document = cl_document_bcs=&gt;create_document( i_type = 'HTM' i_text = gt_text i_subject = gc_subject ). go_send_request-&gt;set_document( go_document ). * loop at it_approvers into wa_approver. go_recipient = cl_cam_address_bcs=&gt;create_internet_address( lv_appr_mid ). go_send_request-&gt;add_recipient( EXPORTING i_recipient = go_recipient i_express = abap_true ). * endloop. gv_sent_to_all = go_send_request-&gt;send( i_with_error_screen = abap_true ). COMMIT WORK. CATCH cx_bcs INTO gx_bcs_exception. gv_error_message = gx_bcs_exception-&gt;get_text( ). WRITE gv_error_message. ENDTRY. IF LV_COUNTER &gt; LV_COUNTER_MAX. LV_EXIT = 'X'. ELSE. LV_EXIT = 'Y'. ENDIF. wa_rec_wf_sts-doc_no = lv_belnr1. wa_rec_wf_sts-comp_code = lv_comp_code. wa_rec_wf_sts-fis_year = lv_gjahr. wa_rec_wf_sts-status = 'In-process'. MODIFY ZFI_REC_WF_ST_DT from wa_rec_wf_sts. COMMIT WORK.</code></pre><P><STRONG>M_UNBLOCK_POSTING:</STRONG></P><P><STRONG>Parameters:<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_11-1771764615838.png" style="width: 531px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375127iB6A0610FBF39855B/image-dimensions/531x39?v=v2" width="531" height="39" role="button" title="ShravanBalaji16897_11-1771764615838.png" alt="ShravanBalaji16897_11-1771764615838.png" /></span><BR /></STRONG></P><pre class="lia-code-sample language-abap"><code> DATA: lt_bkdf TYPE TABLE OF bkdf, lt_bkpf TYPE TABLE OF bkpf, lt_dummy_bseg TYPE TABLE OF bseg, lt_dummy_bsec TYPE TABLE OF bsec, lt_dummy_bsed TYPE TABLE OF bsed, lt_dummy_bset TYPE TABLE OF bset. SELECT SINGLE * FROM bkpf INTO (ls_bkpf) WHERE bukrs = _bkdf-bukrs AND belnr = _bkdf-belnr AND gjahr = _bkdf-gjahr. IF sy-subrc = 0. " Read blocked recurring entry data SELECT SINGLE * FROM bkdf INTO (ls_bkdf) WHERE bukrs = _bkdf-bukrs AND belnr = _bkdf-belnr AND gjahr = _bkdf-gjahr. IF sy-subrc = 0. " Remove Block ls_bkdf-blocked_for_posting = abap_false. ls_bkdf-xdelt = abap_false. " Add records APPEND ls_bkpf TO lt_bkpf. APPEND ls_bkdf TO lt_bkdf. " Update document CALL FUNCTION 'CHANGE_DOCUMENT' TABLES t_bkdf = lt_bkdf t_bkpf = lt_bkpf t_bsec = lt_dummy_bsec t_bsed = lt_dummy_bsed t_bseg = lt_dummy_bseg t_bset = lt_dummy_bset. IF sy-subrc = 0. COMMIT WORK. ENDIF. ENDIF. ENDIF. ENDMETHOD.</code></pre><P><STRONG>M_COMPLETE_MAIL:</STRONG></P><P><STRONG>Parameters:<BR /></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_12-1771764682095.png" style="width: 584px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375128i3AC86537D1A5B41B/image-dimensions/584x120?v=v2" width="584" height="120" role="button" title="ShravanBalaji16897_12-1771764682095.png" alt="ShravanBalaji16897_12-1771764682095.png" /></span></P><pre class="lia-code-sample language-abap"><code> DATA: gc_subject TYPE so_obj_des, " Email subject gc_email_to TYPE adr6-smtp_addr, " Valid email gs_text TYPE soli, " Text used into the email body gc_type_raw TYPE so_obj_tp, " Email type gc_att_type TYPE soodk-objtp, " Attachment type gc_att_subject TYPE sood-objdes. " Attachment title DATA: gt_text TYPE soli_tab, " Table which contains email body text gt_attachment_hex TYPE solix_tab, " Table which contains the attached file gv_sent_to_all TYPE os_boolean, " Receive the information if email was sent gv_error_message TYPE string, " Used to get the error message go_send_request TYPE REF TO cl_bcs, " Email object go_recipient TYPE REF TO if_recipient_bcs, " Who will receive the email go_sender TYPE REF TO cl_sapuser_bcs, " Who is sending the email go_document TYPE REF TO cl_document_bcs, " Email body gx_bcs_exception TYPE REF TO cx_bcs. DATA: e_reason TYPE swcont-value, reason_txt TYPE swcont-value, l_lines TYPE i, object_content TYPE TABLE OF solisti1, subcontainer_all_objects TYPE TABLE OF swr_cont, lv_wa_reason LIKE LINE OF subcontainer_all_objects, lv_no_att TYPE sy-index, document_id TYPE sofolenti1-doc_id, return_code TYPE sy-subrc, ifs_xml_container TYPE xstring, ifs_xml_container_schema TYPE xstring, simple_container TYPE TABLE OF swr_cont, message_lines TYPE TABLE OF swr_messag, message_struct TYPE TABLE OF swr_mstruc, subcontainer_bor_objects TYPE TABLE OF swr_cont. if lv_flag ne 'R'. TRY. go_send_request = cl_bcs=&gt;create_persistent( ). go_sender = cl_sapuser_bcs=&gt;create( 'SAP_WFRT' ). go_send_request-&gt;set_sender( i_sender = go_sender ). CONCATENATE 'Recurring Entry Approved:' lv_comp_code lv_belnr lv_gjahr INTO gc_subject SEPARATED BY space. gs_text-line = '&lt;HTML&gt;&lt;BODY&gt;'. APPEND gs_text TO gt_text[]. CLEAR: gs_text. CONCATENATE 'Dear' lv_init_name ',' INTO gs_text-line SEPARATED BY space. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. CONCATENATE 'Recurring Journal Entry' lv_belnr lv_comp_code lv_gjahr 'has been completely approved.' INTO gs_text-line SEPARATED BY space. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. CONCATENATE 'This is a system generated mail.' 'Please do not reply to this.' INTO gs_text-line SEPARATED BY space. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = '&lt;/BODY&gt;&lt;/HTML&gt;'. APPEND gs_text TO gt_text[]. CLEAR: gs_text. go_document = cl_document_bcs=&gt;create_document( i_type = 'HTM' i_text = gt_text i_subject = gc_subject ). go_send_request-&gt;set_document( go_document ). go_recipient = cl_cam_address_bcs=&gt;create_internet_address( lv_init_mid ). "Add recipient to send request go_send_request-&gt;add_recipient( EXPORTING i_recipient = go_recipient i_express = abap_true ). "Send email and get the result gv_sent_to_all = go_send_request-&gt;send( i_with_error_screen = abap_true ). COMMIT WORK. CATCH cx_bcs INTO gx_bcs_exception. gv_error_message = gx_bcs_exception-&gt;get_text( ). WRITE gv_error_message. ENDTRY. else. DATA: lv_user TYPE bapibname-bapibname. DATA: ls_address TYPE bapiaddr3. DATA: lt_return TYPE TABLE OF bapiret2. lv_user = lv_actual_agent+2(12). CALL FUNCTION 'BAPI_USER_GET_DETAIL' EXPORTING username = lv_user IMPORTING address = ls_address TABLES return = lt_return[]. CALL FUNCTION 'SAP_WAPI_READ_CONTAINER' EXPORTING workitem_id = lv_workitem_id language = sy-langu user = sy-uname IMPORTING return_code = return_code ifs_xml_container = ifs_xml_container ifs_xml_container_schema = ifs_xml_container_schema TABLES simple_container = simple_container message_lines = message_lines message_struct = message_struct subcontainer_bor_objects = subcontainer_bor_objects subcontainer_all_objects = subcontainer_all_objects. * &amp;-----------------------------------------------------------------------------* * Initialize * &amp;-----------------------------------------------------------------------------* lv_no_att = 0. * &amp;-----------------------------------------------------------------------------* * Read the _ATTACH_OBJECTS element * &amp;-----------------------------------------------------------------------------* LOOP AT subcontainer_all_objects INTO lv_wa_reason WHERE element = 'DECISION_NOTE'."'_ATTACH_OBJECTS'. lv_no_att = lv_no_att + 1. document_id = lv_wa_reason-value. ENDLOOP. * &amp;-----------------------------------------------------------------------------* * Read the SOFM Document * &amp;-----------------------------------------------------------------------------* IF document_id IS NOT INITIAL. REFRESH : object_content. CALL FUNCTION 'SO_DOCUMENT_READ_API1' EXPORTING document_id = document_id * FILTER = 'X ' * IMPORTING * DOCUMENT_DATA = TABLES * OBJECT_HEADER = object_content = object_content * OBJECT_PARA = * OBJECT_PARB = * ATTACHMENT_LIST = * RECEIVER_LIST = * CONTENTS_HEX = EXCEPTIONS document_id_not_exist = 1 operation_no_authorization = 2 x_error = 3 OTHERS = 4. IF sy-subrc EQ 0. CLEAR : l_lines. DESCRIBE TABLE object_content LINES l_lines. IF l_lines LT 5. READ TABLE object_content INTO reason_txt INDEX 1. IF sy-subrc EQ 0. e_reason = reason_txt. ENDIF. ENDIF. ENDIF. ENDIF. TRY. "Create send request go_send_request = cl_bcs=&gt;create_persistent( ). "Email FROM... go_sender = cl_sapuser_bcs=&gt;create( 'SAP_WFRT' ). "Add sender to send request go_send_request-&gt;set_sender( i_sender = go_sender ). CONCATENATE 'Recurring Entry Rejected:' lv_comp_code lv_belnr lv_gjahr INTO gc_subject SEPARATED BY space. gs_text-line = '&lt;HTML&gt;&lt;BODY&gt;'. APPEND gs_text TO gt_text[]. CLEAR: gs_text. CONCATENATE 'Dear' lv_init_name ',' INTO gs_text-ine SEPARATED BY space. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. CONCATENATE 'Journal Entry' lv_belnr lv_comp_code lv_gjahr 'has been rejeted by.' ls_address-fullname INTO gs_text-line SEPARATED BY space. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. CONCATENATE 'Rejection Reason:' e_reason INTO gs_text-line SEPARATED BY space. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. CONCATENATE 'This is a system generated mail.' 'Please do not reply to this.' INTO gs_text-line SEPARATED BY space. APPEND gs_text TO gt_text[]. CLEAR: gs_text. gs_text-line = '&lt;br&gt;&lt;/br&gt;'. APPEND gs_text TO gt_text. CLEAR: gs_text. gs_text-line = '&lt;/BODY&gt;&lt;/HTML&gt;'. APPEND gs_text TO gt_text[]. CLEAR: gs_text. go_document = cl_document_bcs=&gt;create_document( i_type = 'HTM' i_text = gt_text * i_length = '12' i_subject = gc_subject ). go_send_request-&gt;set_document( go_document ). go_recipient = cl_cam_address_bcs=&gt;create_internet_address( lv_init_mid ). "Add recipient to send request go_send_request-&gt;add_recipient( EXPORTING i_recipient = go_recipient i_express = abap_true ). "Send email and get the result gv_sent_to_all = go_send_request-&gt;send( i_with_error_screen = abap_true ). COMMIT WORK. CATCH cx_bcs INTO gx_bcs_exception. gv_error_message = gx_bcs_exception-&gt;get_text( ). WRITE gv_error_message. ENDTRY. endif. endmethod.​</code></pre><P><STRONG>NOTE: Notification sent upon Complete Approval or upon Rejection in any one level is incorporated in the same method.</STRONG></P><P>Thus, the class and methods required for the workflow operation has been completed successfully.</P><P><STRONG>Step – 4: </STRONG>Now we need to trigger the Workflow once the Recurring Document is created in FBD1. For which we need to find the suitable BTE (For finding the BTE, refer the process mentioned in Step-2). The BTE for this requirement is <STRONG>“SAMPLE_INTERFACE_00001030”.<BR />Copy this FM in SE37 to a custom one and write the below code.<BR /></STRONG></P><pre class="lia-code-sample language-abap"><code>IF sy-tcode = 'FBD1' OR sy-tcode = 'FBD9' . "Recurring Journal Entry Workflow Event Trigger DATA: lv_objtype TYPE sibftypeid, lv_event TYPE sibfevent, lv_objkey TYPE sibfinstid, lr_event_parameters TYPE REF TO if_swf_ifs_parameter_container, lv_param_name TYPE swfdname, ls_recjour_input TYPE zfi_st_recjour_entry. CONSTANTS: lc_objtype TYPE sibftypeid VALUE 'ZCL_FI_9000_RECURRING_WF', lc_event TYPE sibfevent VALUE 'CREATED', lc_param_name TYPE swfdname VALUE 'ZST_WF_REC_JOUR'. lv_objtype = lc_objtype. lv_event = lc_event. lv_param_name = lc_param_name. ls_recjour_input-wa_bkdf = i_bkdf. ls_recjour_input-wa_bkpf = t_bkpf. ls_recjour_input-wa_bsec = t_bsec. ls_recjour_input-wa_bsed = t_bsed. ls_recjour_input-wa_bseg = t_bseg. ls_recjour_input-wa_bset = t_bset. ls_recjour_input-tcode = sy-tcode . concatenate ls_recjour_input-wa_bkpf-belnr ls_recjour_input-wa_bkpf-bukrs ls_recjour_input-wa_bkpf-gjahr into lv_objkey. CALL METHOD cl_swf_evt_event=&gt;get_event_container EXPORTING im_objcateg = cl_swf_evt_event=&gt;mc_objcateg_cl im_objtype = lv_objtype im_event = lv_event RECEIVING re_reference = lr_event_parameters. TRY. CALL METHOD lr_event_parameters-&gt;set EXPORTING name = lv_param_name value = ls_recjour_input. CATCH cx_swf_cnt_cont_access_denied . CATCH cx_swf_cnt_elem_access_denied . CATCH cx_swf_cnt_elem_not_found . CATCH cx_swf_cnt_elem_type_conflict . CATCH cx_swf_cnt_unit_type_conflict . CATCH cx_swf_cnt_elem_def_invalid . CATCH cx_swf_cnt_container . ENDTRY. TRY. CALL METHOD cl_swf_evt_event=&gt;raise EXPORTING im_objcateg = cl_swf_evt_event=&gt;mc_objcateg_cl im_objtype = lv_objtype im_event = lv_event im_objkey = lv_objkey im_event_container = lr_event_parameters. COMMIT WORK. CATCH cx_swf_evt_invalid_objtype . CATCH cx_swf_evt_invalid_event . ENDTRY. IF sy-subrc &lt;&gt; 0. * WRITE: 'Error occurred while triggering workflow event.' ##NO_TEXT. ENDIF. ENDIF. ENDIF.</code></pre><P><STRONG>STEP – 5: </STRONG>Now we need to create tasks in PFTC, for the methods that were created in STEP-3. This is a very normal procedure of creating the tasks that are to be consumed by the activity in the Workflow Template.</P><P>NOTE: For the User Decision Step, take a copy of the standard decision step (TS00008267) and do the necessary modifications and perform agent assignment. Once done, capture the Agent Assignment in a <STRONG>Customizing TR</STRONG> by running the report&nbsp;<STRONG>RHMOVE30 </STRONG>in<STRONG> SE38.</STRONG></P><P>&nbsp;<STRONG>STEP – 6: </STRONG>I had created Flexible Workflow for this requirement. Open the transaction “SWDD_SCENARIO”. Create the Workflow containers with reference to all the event and the method parameters in the Custom Class created in STEP-3.&nbsp;</P><OL><LI>In the <STRONG>Process Data</STRONG> Tab, provide the class name and the associated event. Do the necessary event binding and activate the event as shown below.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_13-1771764974653.png" style="width: 553px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375129i02665620830D9D2A/image-dimensions/553x123?v=v2" width="553" height="123" role="button" title="ShravanBalaji16897_13-1771764974653.png" alt="ShravanBalaji16897_13-1771764974653.png" /></span><BR />NOTE: Caputre the Event Activation in the same customizing TR as mentioned in STEP - 5.</LI><LI>In the <STRONG>Activities</STRONG> Tab, create the activities for the tasks that were created in STEP-5. Include the User Decision Activity, in the list of activities.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_14-1771765100311.png" style="width: 548px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375130i23CD7AC9A8C4A849/image-dimensions/548x84?v=v2" width="548" height="84" role="button" title="ShravanBalaji16897_14-1771765100311.png" alt="ShravanBalaji16897_14-1771765100311.png" /></span><BR />NOTE: <STRONG>“DISPLAY_TCODE”</STRONG><SPAN> is an activity which we have created for accessing the T-Code “FBD1”.</SPAN></LI><LI><SPAN><SPAN>In the <STRONG>Conditions</STRONG> Tab, we have created one condition. This condition is for stopping the Workflow upon completion of all the agents.<BR /></SPAN></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_15-1771765225148.png" style="width: 565px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375131iE1E9745255004318/image-dimensions/565x98?v=v2" width="565" height="98" role="button" title="ShravanBalaji16897_15-1771765225148.png" alt="ShravanBalaji16897_15-1771765225148.png" /></span></LI><LI>When we create Flexible Workflow, we must create a customized Runtime Class. This Runtime Class helps us to utilize <STRONG>“Instance Methods” </STRONG>upon available events. We need to create a Subclass of the standard Runtime Class “CL_SWF_FLEX_IFS_RUN_APPL_BASE”. Then we can redefine the methods necessary for our purpose. There would be several standard methods which would be useful for several scenarios.<BR /><STRONG>NOTE: For our process, we can redefine below methods, as shown below.</STRONG><BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_16-1771765657479.png" style="width: 561px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375132iC185E849560D1162/image-dimensions/561x31?v=v2" width="561" height="31" role="button" title="ShravanBalaji16897_16-1771765657479.png" alt="ShravanBalaji16897_16-1771765657479.png" /></span><BR /><STRONG>NOTE: First method would get triggered just before the Workflow is about to complete. Second method would trigger upon completion of each activity. Use TaskId as filter, such that procedure only for suitable tasks would run.</STRONG><BR /><P><STRONG>Inside the Result Callback method, utilize the mail notification methods created in STEP-3.</STRONG></P></LI><LI><P>Activate the Workflow. Since we are implementing Flexible Workflow, we need to activate the scenario. Follow the path mentioned below.<BR /><STRONG>SPRO -&gt; ABAP Platform -&gt; Application Server -&gt; Business Management -&gt; SAP Business Workflow -&gt; Flexible Workflow -&gt; Scenario Activation.&nbsp;<BR /></STRONG></P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_20-1771766124016.png" style="width: 572px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375137iAAFEB1B5DA48DBBD/image-dimensions/572x156?v=v2" width="572" height="156" role="button" title="ShravanBalaji16897_20-1771766124016.png" alt="ShravanBalaji16897_20-1771766124016.png" /></span><P><STRONG>NOTE: Provide the Custom Workflow Number and activate the scenario. You can capture this in TR &amp; transport to further landscape.</STRONG></P></LI><LI><P>Now we need to Login to the FIORI launchpad. As Pre-requisites implement <STRONG>“Manage Workflows”</STRONG> &amp; <STRONG>“Manage Workflow Scenarios”</STRONG> applications.<BR /><STRONG>NOTE: In the <STRONG>“Manage Workflows”</STRONG> application create the Workflow, along with the sequence of the steps in which the workflow must be executed.<BR /></STRONG><STRONG>Manage Workflow Header:</STRONG></P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_17-1771765885024.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375134i2D0C34AAB67AAD5A/image-size/medium?v=v2&amp;px=400" role="button" title="ShravanBalaji16897_17-1771765885024.png" alt="ShravanBalaji16897_17-1771765885024.png" /></span><P><STRONG>Execution Steps:<BR /></STRONG></P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_18-1771765927203.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375135iE24283FA6449BA2A/image-size/medium?v=v2&amp;px=400" role="button" title="ShravanBalaji16897_18-1771765927203.png" alt="ShravanBalaji16897_18-1771765927203.png" /></span><BR /><P>Here the maximum level is 4. However, if we keep the maximum approver level less than 4 also, the Workflow will stop at the designated maximum level.&nbsp;This is based the Step-Condition indicated as <STRONG>Final Level</STRONG> in the above screenshot.</P><P>Once created, open the <STRONG>“Manage Workflow Scenarios”</STRONG> application and export the scenario. This will get downloaded as a XML file in the system.</P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ShravanBalaji16897_19-1771765966849.png" style="width: 584px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/375136i00B211BF14634CCB/image-dimensions/584x130?v=v2" width="584" height="130" role="button" title="ShravanBalaji16897_19-1771765966849.png" alt="ShravanBalaji16897_19-1771765966849.png" /></span></LI><LI>Move the Customizing TR and import the downloaded XML file into the testing landscape and to further landscapes.</LI><LI>Upon Complete approval of the workflow, the&nbsp;<STRONG>“BLOCKED_FOR_POSTING” &amp; “XDELT (Deletion_Indicator) </STRONG>fields would be reset. This makes the document eligible for further posting through Perioidic Job Scheduling in <STRONG>F.14</STRONG> Transaction.</LI><LI>Incase if the approver rejects the document, he can provide the <STRONG>Reason for Rejection.</STRONG>&nbsp;This will be sent along with the <STRONG>Rejection Notification</STRONG> to the <STRONG>Initiator of the Workflow</STRONG> (i.e <STRONG>Recurring Entry Document Creator</STRONG>).&nbsp;</LI><LI>The Document Creator can modify according to the Rejection Comments and save the document. The Workflow would get triggered again for another approval cycle.<BR /><STRONG>NOTE: </STRONG><STRONG>I had designed the solution such that the document cannot be edited, unless it is fully approved / rejected. This is an optional solution to be incorporated.&nbsp;</STRONG></LI></OL><P>&nbsp;<STRONG>Conclusion:<BR /></STRONG>Recurring entries simplify financial operations, but without governance, they can introduce compliance risks. By integrating FBD1 with an approval workflow, organizations can achieve the right balance between automation and financial control, ensuring accuracy, transparency, and audit readiness.</P> 2026-02-24T08:51:32.650000+01:00 https://community.sap.com/t5/abap-blog-posts/dynamic-field-manipulation-in-rap-action-popup-a-step-by-step-guide/ba-p/14306555 “Dynamic Field Manipulation in RAP Action Popup – A Step-by-Step Guide” 2026-02-25T11:21:35.588000+01:00 Bikash_R https://community.sap.com/t5/user/viewprofilepage/user-id/1527809 <P><FONT size="4" color="#000000"><U><STRONG><FONT face="times new roman,times">Introduction-</FONT></STRONG></U></FONT></P><P><FONT face="times new roman,times"><FONT color="#000000"><SPAN class=""><SPAN class="">In SAP RAP, actions play a crucial role in triggering business logic from the UI. One powerful feature is the ability to open a parameter dialog (popup) when an action is executed.<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">In this blog, we will explore how to dynamically control fields inside a RAP action popup, including implementing dropdown value help and runtime field manipulation. This step-by-step guide<SPAN>&nbsp;<SPAN class="">demonstrates<SPAN class=""><SPAN>&nbsp;how to design, implement, and test a parameterized RAP action that enhances user interaction in SAP Fiori Elements.<SPAN class=""><BR /></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></FONT></P><P><U><FONT face="times new roman,times" size="4"><STRONG><I>Let's&nbsp;create the tables-</I></STRONG></FONT></U></P><P><FONT face="times new roman,times"><STRONG>Header table-<I><SPAN><BR /></SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>@EndUserText.label : 'Contact Table' @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE @AbapCatalog.tableCategory : #TRANSPARENT @AbapCatalog.deliveryClass : #A @AbapCatalog.dataMaintenance : #RESTRICTED define table zbrt_t_contact { key client : abap.clnt not null; key contact_id : sysuuid_x16 not null; @EndUserText.label : 'First Name' first_name : abap.char(30) not null; @EndUserText.label : 'Middle Name' middle_name : abap.char(30); @EndUserText.label : 'Last Name' last_name : abap.char(30); gender : zbrt_de_gender; @EndUserText.label : 'Date of Birth' dob : abap.dats; @EndUserText.label : 'Age' age : abap.numc(3); @EndUserText.label : 'Telephone' telephone : abap.numc(10); @EndUserText.label : 'Email' email : abap.char(80); active : abap_boolean; created_by : abp_creation_user; created_at : abp_creation_tstmpl; last_changed_by : abp_lastchange_user; last_changed_at : abp_lastchange_tstmpl; }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN><SPAN class=""><SPAN class="">Item&nbsp;<SPAN class=""><SPAN class="">table&nbsp;with foreign key relationship-<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>@EndUserText.label : 'Contact address table' @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE @AbapCatalog.tableCategory : #TRANSPARENT @AbapCatalog.deliveryClass : #A @AbapCatalog.dataMaintenance : #RESTRICTED define table zbrt_t_contaddr { key client : abap.clnt not null; @AbapCatalog.foreignKey.screenCheck : false key contact_id : sysuuid_x16 not null with foreign key [1..*,1] zbrt_t_contact where client = zbrt_t_contaddr.client and contact_id = zbrt_t_contaddr.contact_id; key address_id : sysuuid_x16 not null; key address_sr : abap.numc(2) not null; addr1 : abap.char(30); addr2 : abap.char(30); city : abap.char(20); state : abap.char(30); pincode : abap.numc(6); created_by : abp_creation_user; created_at : abp_creation_tstmpl; last_changed_by : abp_lastchange_user; last_changed_at : abp_lastchange_tstmpl; }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN>Then create the interface view along with association and composition--</SPAN></I></STRONG></FONT></P><P><FONT face="times new roman,times"><STRONG><I><SPAN>Header interface view--</SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>@AbapCatalog.viewEnhancementCategory: [#NONE] @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Contact View' @Metadata.ignorePropagatedAnnotations: true define root view entity Zi_Brt_Contact as select from zbrt_t_contact composition[0..*] of ZI_BRT_CONTADDR as _Address association[1..*] to ZI_BRT_GENDER as _Gender on $projection.Gender = _Gender.GenderCode { key contact_id as ContactId, first_name as FirstName, middle_name as MiddleName, last_name as LastName, gender as Gender, dob as Dob, age as Age, telephone as Telephone, email as Email, active as Active, created_by as CreatedBy, created_at as CreatedAt, last_changed_by as LastChangedBy, last_changed_at as LastChangedAt, _Gender, _Address }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class="">Item interface view--<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>@AbapCatalog.viewEnhancementCategory: [#NONE] @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Address view' @Metadata.ignorePropagatedAnnotations: true define view entity ZI_BRT_CONTADDR as select from zbrt_t_contaddr association to parent Zi_Brt_Contact as _Contact on $projection.ContactId = _Contact.ContactId { key contact_id as ContactId, key address_id as AddressId, key address_sr as AddressSr, addr1 as Addr1, addr2 as Addr2, city as City, state as State, pincode as Pincode, created_by as CreatedBy, created_at as CreatedAt, last_changed_by as LastChangedBy, last_changed_at as LastChangedAt, _Contact }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN>Then create the projection view for both header and item--</SPAN></I></STRONG></FONT></P><P><FONT face="times new roman,times"><STRONG><I><SPAN>Header projection view--</SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Projection view for contact' @Metadata.ignorePropagatedAnnotations: true @Metadata.allowExtensions: true define root view entity zc_brt_contact provider contract transactional_query as projection on Zi_Brt_Contact { key ContactId, FirstName, MiddleName, LastName, // @ObjectModel.text.association: '_Gender' Gender, Dob, Age, Telephone, Email, Active, CreatedBy, CreatedAt, LastChangedBy, LastChangedAt, /* Associations */ _Gender, _Address : redirected to composition child zc_brt_contaddr }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class="">Item projection view--<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Address projection view' @Metadata.ignorePropagatedAnnotations: true @Metadata.allowExtensions: true define view entity zc_brt_contaddr as projection on ZI_BRT_CONTADDR { key ContactId, key AddressId, key AddressSr, Addr1, Addr2, City, State, Pincode, CreatedBy, CreatedAt, LastChangedBy, LastChangedAt, /* Associations */ _Contact : redirected to parent zc_brt_contact }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class="">Then create Behavior definition on interface view--<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>unmanaged implementation in class zbrt_cl_contact_saver unique; strict ( 2 ); with draft; define behavior for Zi_Brt_Contact alias u_contact implementation in class zbrt_cl_bp_contact_u unique draft table zbrt_t_contact_d late numbering lock master total etag LastChangedAt authorization master ( instance ) //etag master &lt;field_name&gt; { create; update ( features : instance ); delete ( features : instance ); field ( readonly ) ContactId, Age; association _Address { create (features : instance); with draft; } determination calculate_age on modify { field Dob; } action ( features : instance ) setstatus result[1] $self; action change_field_value parameter ZI_BRT_STATUS_PARAM result[1] $self; draft action Edit; draft action Activate optimized; draft action Resume; draft action Discard; draft determine action Prepare; mapping for zbrt_t_contact control zbrt_s_contact { ContactId = contact_id; FirstName = first_name; MiddleName = middle_name; LastName = last_name; Gender = gender; Dob = dob; Age = age; Telephone = telephone; Email = email; Active = active; CreatedBy = created_by; CreatedAt = created_at; LastChangedBy = last_changed_by; LastChangedAt = last_changed_at; } } define behavior for ZI_BRT_CONTADDR alias u_contadd implementation in class zbrt_cl_bp_contadd_u unique draft table zbrt_t_contadd_d late numbering lock dependent by _Contact authorization dependent by _Contact { update (features : instance); delete (features : instance); field ( readonly ) ContactId, AddressId, AddressSr; association _Contact{with draft;} mapping for zbrt_t_contaddr control zbrt_s_contaddr { ContactId = contact_id; AddressId = address_id; AddressSr = address_sr; Addr1 = addr1; Addr2 = addr2; City = city; State = state; Pincode = pincode; CreatedBy = created_by; CreatedAt = created_at; LastChangedBy = last_changed_by; LastChangedAt = last_changed_at; } }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class="">Behavior definition on projection view--<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></I></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>projection; strict ( 2 ); use draft; define behavior for zc_brt_contact //alias u_contact use etag { use create; use update; use delete; use action setstatus; use action change_field_value; use action Edit; use action Activate; use action Resume; use action Discard; use action Prepare; use association _Address { create; with draft; } } define behavior for zc_brt_contaddr //alias u_contaddr { use update; use delete; use association _Contact { with draft; } }</code></pre><P><FONT face="times new roman,times"><STRONG><I><SPAN><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class=""><SPAN class="">Service definition--<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></I></STRONG></FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_0-1771930805561.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376308i443F6B7435990502/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_0-1771930805561.png" alt="Bikash_R_0-1771930805561.png" /></span></P><P><STRONG><EM><FONT face="times new roman,times"><SPAN class=""><SPAN class="">Service binding--<BR /></SPAN></SPAN></FONT></EM></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_1-1771930862637.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376309i0C05A399315A3C69/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_1-1771930862637.png" alt="Bikash_R_1-1771930862637.png" /></span></P><P><STRONG><FONT face="times new roman,times"><SPAN class=""><SPAN class="">Actions buttons in UI-<BR /></SPAN></SPAN></FONT></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_0-1771936749696.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376365iBC27DF91F742104E/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_0-1771936749696.png" alt="Bikash_R_0-1771936749696.png" /></span></P><P><STRONG><FONT face="times new roman,times"><SPAN class=""><SPAN class="">This is the action button declared in the&nbsp;behavior&nbsp;definition--&gt;</SPAN></SPAN></FONT></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_3-1771930968187.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376312i989697525219884F/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_3-1771930968187.png" alt="Bikash_R_3-1771930968187.png" /></span></P><P><FONT face="times new roman,times"><STRONG><SPAN class=""><SPAN class="">This method&nbsp;<SPAN class=""><SPAN class="">setstatus<SPAN class=""><SPAN class="">&nbsp;is&nbsp;<SPAN class="">a&nbsp;<SPAN class=""><SPAN class="">RAP<SPAN class="">&nbsp;Action implementation<SPAN class=""><SPAN class="">.<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">It&nbsp;<SPAN class=""><SPAN class="">toggles the status<SPAN class=""><SPAN class="">&nbsp;(<SPAN class=""><SPAN class="">ACTIVE ↔ INACTIVE<SPAN class=""><SPAN class="">) of a&nbsp;<SPAN class=""><SPAN class="">Contact<SPAN class=""><SPAN class="">&nbsp;entity.<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></STRONG></FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_4-1771931040324.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376313iE48E54E56138C5B2/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_4-1771931040324.png" alt="Bikash_R_4-1771931040324.png" /></span></P><P><STRONG><FONT face="times new roman,times">%tky-&nbsp;</FONT></STRONG></P><UL><LI><FONT face="times new roman,times"><FONT face="times new roman,times">Technical key&nbsp;</FONT></FONT></LI><LI><FONT face="times new roman,times">Required to update the&nbsp;<STRONG>same instance&nbsp;that was read&nbsp;</STRONG></FONT></LI><LI><STRONG><STRONG><FONT face="times new roman,times">Mandatory in&nbsp;MODIFY ENTITIES</FONT></STRONG></STRONG></LI></UL><P><FONT face="times new roman,times"><STRONG>UPDATE&nbsp;FIELDS&nbsp;( active&nbsp;)--&gt;</STRONG></FONT></P><UL><LI><FONT face="times new roman,times"><FONT face="times new roman,times">Only updates the&nbsp;active&nbsp;field&nbsp;</FONT></FONT></LI><LI><FONT face="times new roman,times"><FONT face="times new roman,times">Prevents accidental changes to other fields</FONT></FONT></LI></UL><P><STRONG><FONT face="times new roman,times">After declaring action name in the&nbsp;behavior&nbsp;definition, we need to declare it in the metadata extension also--</FONT></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_5-1771931176287.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376314iCEAEC9C01CDCBCFF/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_5-1771931176287.png" alt="Bikash_R_5-1771931176287.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_6-1771931235725.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376315iB853799C233AF1A7/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_6-1771931235725.png" alt="Bikash_R_6-1771931235725.png" /></span></P><P><FONT face="times new roman,times"><SPAN>In above we can see the action button name&nbsp;<STRONG><I><SPAN>Change Status<SPAN>&nbsp;in the UI<SPAN>&nbsp;</SPAN></SPAN></SPAN></I></STRONG></SPAN></FONT></P><P><FONT face="times new roman,times"><SPAN>Based on the Active&nbsp;status&nbsp;it is going to change.<SPAN>&nbsp;</SPAN></SPAN></FONT></P><P><STRONG><FONT face="times new roman,times">Let's&nbsp;see--</FONT></STRONG></P><P><FONT face="times new roman,times"><STRONG>Now the field&nbsp;abc&nbsp;-&gt; Active status is Yes -&gt; click on the Change Status button -&gt; now it will become No.&nbsp;</STRONG></FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_7-1771931249530.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376316iF2F8F6723B81B7A5/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_7-1771931249530.png" alt="Bikash_R_7-1771931249530.png" /></span></P><P><FONT face="times new roman,times"><EM><U><FONT color="#000000"><STRONG>IMP&nbsp;- </STRONG></FONT></U></EM><FONT color="#000000">Now here we have another action button which is a parameterized action button which is declared </FONT><FONT color="#000000">using<STRONG>&nbsp;abstract&nbsp;entity.</STRONG></FONT></FONT></P><P><STRONG><FONT face="times new roman,times">Change-Field-Value.<SPAN><FONT face="times new roman,times"><BR /></FONT></SPAN></FONT></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_8-1771931458286.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376317i5D3F030FF7E3B3FF/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_8-1771931458286.png" alt="Bikash_R_8-1771931458286.png" /></span></P><P><STRONG><FONT face="times new roman,times"><SPAN class="">For that we have already created one&nbsp;<SPAN class="">Abstract entity --<BR /></SPAN></SPAN></FONT></STRONG></P><pre class="lia-code-sample language-abap"><code>@EndUserText.label: 'Status parameter' @Metadata.allowExtensions: true define abstract entity zi_brt_status_param { .defaultValue : 'X' @EndUserText.label: 'Active' active : abap_boolean; .defaultValue: #( 'ELEMENT_OF_REFERENCE_ENTITY : Telephone' ) @EndUserText.label: 'Telephone' telephone : abap.numc(10); }</code></pre><P><STRONG><FONT face="times new roman,times"><SPAN class=""><SPAN class=""><SPAN class="">Then declared the same action name in the metadata also-<SPAN class=""><SPAN class="">&nbsp;<BR /></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_9-1771931629300.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376318iF10FD686452548BA/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_9-1771931629300.png" alt="Bikash_R_9-1771931629300.png" /></span></P><P><STRONG><FONT face="times new roman,times"><SPAN class=""><SPAN class="">See the logic--<BR /></SPAN></SPAN></FONT></STRONG></P><pre class="lia-code-sample language-abap"><code>METHOD change_field_value. DATA(ls_param) = VALUE #( keys[ 1 ]-%param ). READ ENTITIES OF zi_brt_contact IN LOCAL MODE ENTITY u_contact ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(lt_contact). MODIFY ENTITIES OF zi_brt_contact IN LOCAL MODE ENTITY u_contact UPDATE FIELDS ( active telephone ) WITH VALUE #( FOR lwa_contact IN lt_contact ( %tky = lwa_contact-%tky %data-active = ls_param-active %data-telephone = ls_param-telephone ) ). result = VALUE #( FOR lwa_contact IN lt_contact ( %key = lwa_contact-%key %param = CORRESPONDING #( lwa_contact ) ) ). ENDMETHOD.</code></pre><P><FONT face="times new roman,times"><SPAN>This is an&nbsp;<STRONG><SPAN>action implementation method<SPAN>&nbsp;inside the Behavior Implementation Class.<SPAN>&nbsp;</SPAN></SPAN></SPAN></STRONG></SPAN></FONT></P><P><FONT face="times new roman,times"><SPAN>It updates:<SPAN>&nbsp;</SPAN></SPAN></FONT></P><UL><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><STRONG><SPAN>active</SPAN></STRONG></FONT></FONT></LI><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><STRONG><SPAN>telephone</SPAN></STRONG></FONT></FONT></LI></UL><P><STRONG><FONT size="3"><FONT face="times new roman,times">based on the values entered in the&nbsp;RAP action popup parameter dialog.&nbsp;</FONT></FONT></STRONG></P><P><FONT face="times new roman,times"><SPAN><STRONG><SPAN><SPAN><SPAN><SPAN><STRONG><SPAN>Fetch Action Parameters from Popup</SPAN></STRONG></SPAN></SPAN></SPAN></SPAN></STRONG></SPAN></FONT></P><pre class="lia-code-sample language-abap"><code>DATA(ls_param) = VALUE #( keys[ 1 ]-%param ).</code></pre><UL><LI><FONT face="times new roman,times"><SPAN>keys&nbsp;→&nbsp;contains&nbsp;selected instances + action parameters</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>%param&nbsp;→ holds popup field values entered by user</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>keys[&nbsp;1 ]&nbsp;→ since action usually triggered on selected row(s)</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><P><FONT face="times new roman,times"><STRONG><SPAN>Meaning:</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times"><SPAN>We are extracting the&nbsp;</SPAN><STRONG><SPAN>parameter values entered in the popup</SPAN></STRONG><SPAN>&nbsp;into structure</SPAN><STRONG><SPAN>&nbsp;ls_param.</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times"><SPAN>If popup had:</SPAN><SPAN>&nbsp;</SPAN></FONT></P><UL><LI><FONT face="times new roman,times"><SPAN>Active = ‘X’</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>Telephone = ‘9876543210’</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><P><FONT face="times new roman,times"><SPAN>Those values now sit in&nbsp;</SPAN><STRONG><SPAN>ls_param.</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times"><STRONG><SPAN>Read Current Entity Data--</SPAN></STRONG></FONT></P><pre class="lia-code-sample language-abap"><code>READ ENTITIES OF zi_brt_contact IN LOCAL MODE ENTITY u_contact ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(lt_contact).</code></pre><UL><LI><FONT face="times new roman,times"><SPAN>Reading selected records from BO</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>IN LOCAL MODE&nbsp;→ no DB commit, transactional buffer</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>WITH CORRESPONDING&nbsp;#( keys&nbsp;)&nbsp;→ read only selected instances</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>Result stored in&nbsp;lt_contact</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><P><FONT face="times new roman,times"><STRONG><SPAN>Why&nbsp;required?</SPAN></STRONG><SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times"><SPAN>Because:</SPAN><SPAN>&nbsp;</SPAN></FONT></P><UL><LI><FONT face="times new roman,times"><SPAN>We need technical key&nbsp;%tky</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>We need current data before updating</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><UL><LI><FONT face="times new roman,times"><SPAN>EML update requires&nbsp;%tky</SPAN><SPAN>&nbsp;</SPAN></FONT></LI></UL><P><STRONG><FONT face="times new roman,times"><SPAN class=""><SPAN class="">Update Fields Using MODIFY ENTITIES-<BR /></SPAN></SPAN></FONT></STRONG></P><pre class="lia-code-sample language-abap"><code>MODIFY ENTITIES OF zi_brt_contact IN LOCAL MODE ENTITY u_contact UPDATE FIELDS ( active telephone ) WITH VALUE #( FOR lwa_contact IN lt_contact ( %tky = lwa_contact-%tky %data-active = ls_param-active %data-telephone = ls_param-telephone ) ).</code></pre><P><FONT face="times new roman,times"><SPAN><STRONG>We are updating:</STRONG><SPAN>&nbsp;</SPAN></SPAN></FONT></P><UL><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>active<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>telephone</SPAN></FONT></FONT></LI></UL><P><FONT face="times new roman,times">for each selected instance.<SPAN>&nbsp;</SPAN></FONT></P><P><FONT face="times new roman,times"><STRONG><SPAN>Important Points:<SPAN>&nbsp;</SPAN></SPAN></STRONG></FONT></P><P><FONT face="times new roman,times"><SPAN>✔ %tky&nbsp;→ technical key&nbsp;required&nbsp;to&nbsp;identify&nbsp;instance<SPAN>&nbsp;<BR /><SPAN>✔ %data-fieldname → actual field update<SPAN>&nbsp;<BR /><SPAN>✔ UPDATE FIELDS → performance optimized (only those 2 fields updated)<SPAN>&nbsp;</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></P><P><FONT face="times new roman,times"><STRONG><SPAN><U>Note -</U><STRONG><SPAN>&nbsp;<SPAN>Even though popup opened per selected row, internally RAP still processes in&nbsp;<STRONG><SPAN>mass-enabled mode<SPAN>.<SPAN>&nbsp;</SPAN></SPAN></SPAN></STRONG></SPAN></SPAN></STRONG></SPAN></STRONG></FONT></P><P><FONT face="times new roman,times"><SPAN>That’s&nbsp;why:<BR /></SPAN></FONT></P><pre class="lia-code-sample language-abap"><code>FOR lwa_contact IN lt_contact</code></pre><P><FONT face="times new roman,times"><STRONG>This allows:</STRONG></FONT></P><UL><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>Single&nbsp;selection<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>Multiple&nbsp;selection<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>Bulk update</SPAN></FONT></FONT></LI></UL><P><STRONG>Return Result to UI</STRONG></P><pre class="lia-code-sample language-abap"><code>result = VALUE #( FOR lwa_contact IN lt_contact ( %key = lwa_contact-%key %param = CORRESPONDING #( lwa_contact ) ) ).</code></pre><P><STRONG><FONT face="times new roman,times">After update:&nbsp;</FONT></STRONG></P><UL><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>Returning updated instance(s)<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT face="times new roman,times"><FONT face="times new roman,times"><SPAN>%key&nbsp;→&nbsp;identifies&nbsp;updated instance<SPAN>&nbsp;</SPAN></SPAN></FONT></FONT></LI><LI><FONT face="times new roman,times"><SPAN>%param&nbsp;→ sends data back to UI<BR /><BR /></SPAN></FONT><TABLE border="1" width="65.12399106571549%"><TBODY><TR><TD width="100%"><FONT size="2"><FONT size="2"><STRONG><FONT face="times new roman,times"><SPAN class=""><SPAN class="">User clicks Action<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">↓<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">Popup opens<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">↓<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">User enters Active + Telephone<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">↓<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">%param<SPAN class="">&nbsp;receives values<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">↓<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">READ ENTITIES → fetch selected records<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">↓<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">MODIFY ENTITIES → update selected instances<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">↓<SPAN class=""><SPAN class="">&nbsp;<BR /><SPAN class=""><SPAN class="">Return result → UI refresh</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></FONT></STRONG></FONT></FONT></TD></TR></TBODY></TABLE></LI></UL><P><STRONG><FONT face="times new roman,times"><SPAN class="">Let's&nbsp;see how it works--<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_1-1771932726068.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376323iCAD4E0E05D1E2575/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_1-1771932726068.png" alt="Bikash_R_1-1771932726068.png" /></span><BR /></SPAN></FONT></STRONG></P><P><STRONG><FONT face="times new roman,times"><SPAN class="">Now&nbsp;I&nbsp;have selected one record -&gt; Bikash -&gt; which&nbsp;telephone Num&nbsp;is&nbsp;there,&nbsp;and Active status is Yes -&gt; click on Change-field-value -&gt;<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_2-1771932765787.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376324i65D1DAC0B1451C3A/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_2-1771932765787.png" alt="Bikash_R_2-1771932765787.png" /></span><BR /></SPAN></FONT></STRONG></P><P><STRONG><FONT face="times new roman,times"><SPAN class="">-&gt; we can see the&nbsp;pop-up&nbsp;where we can change the Active status&nbsp;drop down&nbsp;and Telephone number as well -&gt;&nbsp;let’s&nbsp;do&nbsp;the changes&nbsp;and see -&gt;<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_3-1771932901745.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376325i2272966A69A38649/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_3-1771932901745.png" alt="Bikash_R_3-1771932901745.png" /></span><BR /></SPAN></FONT></STRONG></P><P><STRONG><FONT face="times new roman,times"><SPAN class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Bikash_R_4-1771932912741.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/376326iD6E93E3586DDFAA3/image-size/large?v=v2&amp;px=999" role="button" title="Bikash_R_4-1771932912741.png" alt="Bikash_R_4-1771932912741.png" /></span></SPAN></FONT></STRONG></P><P><FONT face="times new roman,times"><STRONG><I><SPAN>In the&nbsp;above,&nbsp;we can see the changes.&nbsp;<BR /><FONT size="4"><BR />Conclusion--</FONT></SPAN></I></STRONG></FONT></P><P><FONT face="times new roman,times"><SPAN>In this blog, we explored how to implement dynamic field manipulation inside a RAP action popup using a parameterized action. We walked through extracting popup parameters using&nbsp;%param, reading selected instances via&nbsp;READ ENTITIES, and performing controlled updates using&nbsp;MODIFY ENTITIES&nbsp;in local mode. Finally, we ensured proper UI synchronization by returning the updated result set back to the Fiori Elements application.&nbsp;</SPAN></FONT></P><P><STRONG><FONT face="times new roman,times"><SPAN class="">Thanks--</SPAN></FONT></STRONG></P> 2026-02-25T11:21:35.588000+01:00 https://community.sap.com/t5/technology-blog-posts-by-members/sap-build-work-zone-tile-opens-content-federation-but-app-fails-with-ip/ba-p/14339460 SAP Build Work Zone: Tile Opens(content federation) but App Fails with ‘IP Address Cannot Be Found 2026-03-02T10:49:06.511000+01:00 OmPrakashJha https://community.sap.com/t5/user/viewprofilepage/user-id/5102 <DIV><P>In my SAP Build Work Zone (Standard Edition) environment, I faced an issue where a <STRONG>dynamic tile loaded successfully&nbsp;through content federation</STRONG>, but clicking the tile caused the application to fail with a browser error:</P><BLOCKQUOTE><P><STRONG>ERR_NAME_NOT_RESOLVED – The IP address of the server could not be found</STRONG></P></BLOCKQUOTE><P>The failing URL always contained a <STRONG>very long auto‑generated hostname.</STRONG></P><P>&nbsp;</P><DIV>Interestingly, the dynamic tile itself worked correctly (e.g., OData count displayed), but navigating to the corresponding SAP Fiori app consistently failed. This clearly indicated that the issue was not with backend connectivity or destinations, but with the <STRONG>content runtime URL</STRONG> generated by Work Zone.</DIV><DIV>&nbsp;</DIV><DIV>Please refer the screenshots.</DIV></DIV> 2026-03-02T10:49:06.511000+01:00