Product Information
How-To: Avoid Purchase Order creation once the Purchase Requisition Quantity is exceeded / BAdI Implementation for Final Check Before Save
Table of Contents
Business Background
You would like to create a Purchase Order based on the Purchase Requisition, but once the requested quantity is exceeded, you won’t like to allow further creations of Purchase Orders related to this Purchase Requisition? Then you are right here in this How-To-Blog.
The SAP standard behavior is that the Purchase Requisition is a reference document and that the requested quantity is not a hard limit. With that you are quickly able to create another Purchase Order, e.g. on short notice, using the same Purchase Requisition as template. But some wouldn’t like to have this, so you can implement the final check BAdI for Purchase Order.
Role / Prerequisites
For implementing a BAdI you need ABAP Know-How and the authorization (usually the Admin, role SAP_BR_ADMINISTRATOR) to create it.
Steps:
- Logon to your Fiori Launchpad
- Open the app “Custom Field and Logic” (#CustomField-develop)
- Move to tab “Custom Logic”
- Press “Create” button in upper right corner to create a new BAdI implementation
- A popup opens,
- Select the Business Context: “Procurement: Purchasing Document”
- Select the BAdI: “Check of Purchase Order Before Saving”
- Add a meaningful description
- Change Implementation ID, if wished
- Press “Create”
Remark – Error in create scenario: In case the Implementation ID is greyed out (like below) and you get an error popup once you pressed on “Create” having the error message: “Implementation YY1_PO_BEFORE_SAVE already exists. Use the editor view to create a draft.” Press “Ok” and “Cancel” in the creation dialog and search for the implementation by using the search field above the table and “YY1_PO_BEFORE_SAVE” as search term. Once the search result is shown press on the line to open the existing implementation. This implementation then needs to be enhanced. |
Once you pressed create (or opened your existing implementation), you will find the screen below, where you can implement your coding, having a sample implementation from SAP.
Within available fields you can see the internal tables you can use for further processing. The both with _db representing the data from database, in case the Purchase Order was already saved and is in edit mode right now.
Once the implementation is finished you can press “Publish” to make it active.
Implementation of check logic
Goal
Check logic to throw an error message in case the open quantity of a Purchase Requisition Item is exceeded during Purchase Order creation
5 Steps for the Example Implementation
Step 1: Get the quantity of the Purchase Order Items per Purchase Requisition Item
Step 2: Loop through used Purchase Requisition Items and get the open quantity
Step 3: Handle change mode of a Purchase Order – calculate quantity correctly
Step 4: How-To throw a error message
Step 5: Round-Off
Step 1: Get the quantity of the Purchase Order Items per Purchase Requisition Item
Step 1 |
|
We are selecting from the Purchase Order Items (@purchaseorderitems), which quantity was entered over all purchase order items, summed up by purchase requisition item. We store all these data in an internal table called lt_pr_grouped_qty having three columns (Purchase Requisition – purchaserequisition, Purchase Requisition Item – purchaserequistionitem, Total Quantity Used in current Purchase Order – pr_total_qty).
Step 2: Loop through used Purchase Requisition Items and get the open quantity
Step 1 |
|
Step 2.1 |
|
Step 2.2 |
|
Step 2.3 |
|
Step 2.1 |
|
Afterwards we are looping through the just created internal table lt_pr_grouped_qty (Step 2.1). Within that we are selecting from the database the total requested quantity and the already ordered quantity per Purchase Requisition Item using the item we have currently at our loop-position (Step 2.2). Then we do simply mathematics, from the requested quantity subtracting the ordered quantity and the entered quantity in the Purchase Order (total quantity of all items referring to the same Purchase Requisition Item) (Step 2.3).
Step 3: Handle change mode of a Purchase Order – calculate quantity correctly
Step 2.3 |
|
Step 3.1 |
|
Step 3.2 |
|
Step 3.3 |
|
Step 3.1 |
|
Step 2.1 |
|
After the calculation of Step 2.3 and the end of our loop, we need to handle the change mode. The Purchase Order was ordered, but afterwards something needs to be adopted related to the quantity. So the already ordered quantity is fine and should not effect here, just the difference should be relevant. First (Step 3.1) we need to check whether a purchaser oder is already existing, so we are checking for a Purchase Order Number. Then we are selecting similar as in Step 1, but at this time from the stored Purchase Order Items (@purchaseorderitems_db) and based on the current Purchase Requisition Item we have in our loop (Step 3.2). The same Purchase Requisition Item could be used for multiple Purchase Order Items, so we are looping through all and adding the already ordered quantity again in our calculation as those are not relevant anymore and the Purchase Requisition doesn’t consider them as open (Step 3.3).
Step 4: How-To throw a error message
Step 3.3 |
|
Step 4.1 |
|
Step 4.2 |
|
Step 4.3 |
|
Step 4.4 |
|
Step 3.1 |
|
Step 2.1 |
|
The quantity stored in variable lv_qty is below zero, in case you are trying to order more then available, based on the quantity in the purchase requisition (see calculation above). In case it is below zero, we would like to throw an error and therewith prevent the saving of the Purchase Order (Step 4.1). For having a nice error text, we are converting the quantity to positive value (Step 4.2). For demo purpose we are raising an hardcoded error message. The ‘E’ in ls_message-messagetype indicates the criticality as error and ls_message-messagevariable1 is used for our own build text having the Purchase Requisition Item and the exceeded quantity included (Step 4.3) An example on how to use a message code is shown below. In Step 4.4 we append our ls_message to the returning parameter messages where all message are stored, in case we have multiple.
Step 5: Round-Off
* If a translatable text for the message is needed please use code lists. For on how this can be done in the coding uncomment the lines commented * by an " and replace the CDS yy1_mm_po_ext fields by yours created in your code list. In the code list the message text and its translation is stored. * The text is then read implicitily by the used language if the translation is available in the code list SELECT SINGLE FROM yy1_mm_po_ext fields description WHERE code = '01' INTO @data(lv_message). IF sy-subrc = 0. * If the quantity is exceeded an error message is raised from a message class * The error prevents a saving of the purchase order, i.e. the purchasing group can not be changed anymore ls_message-messagetype = 'E'. ls_message-messagevariable1 = lv_message. APPEND ls_message TO messages. ENDIF. |
As mentioned in Step 4, if you would like to have translatable error message, you can orient yourself on below code snippet, which is also part of SAP provided sample implementation of this BAdI.
So a custom CDS view can be created where the description is read out per code and can be translated.
Complete Implementation of this example
* The example implementation shows how it is prevented that the purchase order can be created once the purchase requisistion* quantity has exceeded * Structure for messages DATA: ls_message LIKE LINE OF messages.
|
Disclaimer: The usage of the coding example is on your own risk. SAP is providing this as an example only, there is no claim for completeness and infallibility. SAP will not support in case of any issues related to this implementation.
Thanks for sharing Kevin, its very helpful.
Thanks Kevin for sharing this, I have created a bridge KBA 2893882 - BAdI Implementation for Final Check Before Saving PO, hope this help.
Thanks Kevin for this solution!
Nicely done! 😉
Thanks a lot for the sharing1
Very well explained!
Thanks Kevin for your sharing.
Thanks for the info and efforts put in this blog!
However, isn't the requirement can be achieved just through a system message control as an error for PO order quantities which exceeds the referenced PR quantity!!
Thanks