Introduction:
In this blog, I will try to demonstrate the functionality of mass purchase order reprice in SAP S/4 HANA.
The pandemic lead to a massive shutdown followed by a slowdown and cause supply chain disruption. Disruption in the supply chain, raising fuel and freight costs often leads to frequent price changes from the vendors (especially oversees long lead time items). As a buyer, it’s important to catch up with frequent and fast changes to make sure the landed cost of the product is correct and 3-way match happens as accurately as possible. This blog will help on how to achieve the solution.
Prerequisites:
- Price update from the vendor will be updated on Purchasing Info Record as a new valid condition record.
Standard SAP options:
Below is the standard SAP option that was explored:
- Standard SAP has t-code: MEI1 which allows updating PO based on condition changes, but standard SAP looks at the PO creation date and condition validity period date and updates the price.
- It was also found that once we process records using MEI1, it is deleting the Table: WIND entries for that vendor of all the items. That means as a buyer, if you want to work on certain items on the PO the next day, you lost visibility of price updates.
Both of the above challenges force me to think of a custom solution.
Solution Approach/Design:
- Create a Fiori tile as per the below layout
- No of Day in the Past*: Mandatory; This is for performance. From day of execution, how many days back do we want to go for the document date; by default 180 days.
- Purchasing Group: Mandatory; Multiple selection drop-down; Validation: T024- T024; E: Purchasing Group Required or E: Invalid Purchasing Group.
- Purchasing Document Type: Optional; Multiple selection drop-down; Validation: T161- BSART; E: Invalid Document type.
- Supplier: Optional; Multiple selection drop-down; Validation: LFA1- LIFNR; E: Invalid Supplier.
- Supplier Subrange: Optional; Multiple selection drop-down; Validation: WYT1- LTSNR; E: Invalid Supplier Subrange.
- Plant#: Optional; Multiple selection drop-down; Validation: T001W-WERKS; E: Invalid Plant.
- Material Group#: Optional; Multiple selection drop-down; Validation: T023-MATKL; E: Invalid material group.
- Material#: Optional; Multiple selection drop-down; Validation: MARC-MATNR; E: Invalid material.
- Next Period Price/Currency: Optional;
- Price Over-Ride: Optional
- Future Cost Match: Optional; drop-down; values are Yes Or No
- Fiori tile validates the data keyed in by the user and captures the appropriate error message in case of errors as stated above.
- After validating input screen data, once the user clicks on go, the program does the following:
- Based on the input, fetch the only open PO(s) undelete and without Free of Charge. Open PO(s) can be found where EKPO-ELIKZ not equal to X and undeleted PO(s) can be found where EKPO-LOEKZ is not equal to L and EKPO- REPOS = X (Excluding Free PO(s) as well).
- Only fetch the PO(s) where item category EKPO-PSTYP not equal to 2 – Consignment and 7 – Stock Transfer (Basically, we don’t want consignment and stock transfer PO(s) as it doesn’t have net price).
- Below are the fields and logic:
Field(s) | Logic |
Purchase Order | From EKPO-EBELN |
Vendor | From EKKO-LIFNR |
Vendor Name | Pass Vendor from EKKO to LFA1 and get LFA1-NAME1 |
Supplier Subrange | From EKPO-LTSNR |
Supplier Subrange Description | Pass Vendor and Subrange to WYT1 and get WYT1-LTSBZ |
Purchasing Group | From EKKO-EKGRP |
Purchasing Group Name | Pass the purchasing group code to T024 and get T024 – EKNAM. |
Document Type | From EKKO-BSART |
Item No | EKPO-EBELP |
Item Category | EKPO-PSTYP |
Material | EKPO-MATNR |
Material Group | EKPO-MATKL |
Material Group Description | Pass material group to T023 and get T023- WGBEZ |
Plant | EKPO-WERKS |
Material Description | MARA-MAKTX |
PO Creation Date | EKKO-AEDAT |
PO Quantity | EKPO-MENGE |
Ordering Unit | EKPO-MEINS |
Conf. Control | EKPO-BSTAE |
Inbound Delivery | Pass PO number, item number, Confirm. Cat.: LA to EKES and get the inbound delivery number. If multiple found, then sort in descending order and get the latest one. |
PO History | Pass PO and item to EKBE and see entries found. If entry is there, then show the graph. Note: T-code: ME2N is prime example on how to show the graph. If developer can find, then we should leverage that. |
PO Item Delivery Date | Pass PO and item number to EKET and get EKET-EINDT |
Price Overwrite | Pass PO to Table: EKKO and get the Doc. Condition No. (EKKO- KNUMV). Pass Condition No. To table: PRCD_ELEMENTS with PO item number and Inactive condition (KINAK) as blank and see if we have PBXX. If yes then show PBXX else blank |
PO Net Price/Currency | EKPO-NETPR/EKKO-WAERS (for example $2800/USD) |
PO Price Unit/Ordering Price Unit | EKPO-PEINH/EKPO-BPRME (for example 100/EA) |
Current Period Validity Date (From – to) |
Note: Within PB00 pricing team is loading price in tables: A017 and A018. If the A017 record then gets trigger else it will go to A018. ***************************************************** Logic: (Developer can explore functional module. I have tried using ME_GET_INFORECORD_CONDITIONS which works fine for PB00 and PB01) Pass Application – KAPPL = M, Condition Type – KSCHL = PB00, Vendor – LIFNR, Material – MATNR, Purchasing Org – EKORG, Plant – WERKS, Info Type – from PO line to Table: A017 and get the condition record number where Valid From < = System Date and Valid To > = System Date. Pass all the records to KONP, sort by ascending order and select 1st non-delete record. If no record is found then go to next. Pass Application – KAPPL = M, Condition Type – KSCHL = PB00, Vendor – LIFNR, Material – MATNR, Purchasing Org – EKORG, Plant – WERKS, Info Type – from PO line to Table : A018 and get the condition record number where Valid From < = System Date and Valid To > = System Date. Pass all the records to KONP, sort by ascending order and select 1st non-delete record. If no record found, then go to next. Also get A017-DATAB to A017-DATBI or A018-DATAB to A018-DATBI for valid record |
Current Period Price/Currency | For the valid condition record get the KONP-KBETR/KONP-KONWA (For example $284/USD) |
Current Period Price Unit/UoM | Also get the KONP-KPEIN/KONP-KMEIN (For example 100/LB) |
Scale Exist? (Flag Yes or No) | If KONP- KZBZG has value, then Scale Exist = Yes else No |
Apply Updated Cost | Checkbox |
Yes or No value for PO Price Vs. Next Period Price | Compare PO Net Price/Current, PO Price Unit/Ordering Price Unit with Next Period Price/Currency and Next Period Price Unit/UoM. If it’s matching, then show Yes else No. |
Previous Period Validity Date (From – to) |
Pass Application – KAPPL = M, Condition Type – KSCHL = PB00, Vendor – LIFNR, Material – MATNR, Purchasing Org – EKORG, Plant – WERKS, Info Type – from PO line to Table : A017 and get the condition record number where Valid From < System Date. Pass all the records to KONP, sort by descending order and select 1st non-delete record. If no record found then go to next. Pass Application – KAPPL = M, Condition Type – KSCHL = PB00, Vendor – LIFNR, Material – MATNR, Purchasing Org – EKORG, Plant – WERKS, Info Type -from PO line to Table: A018 and get the condition record number where Valid From < System Date. Pass all the records to KONP, sort by descending order and select 1st non-delete record. If no record found, then go to next. Also, get A017-DATAB to A017-DATBI or A018-DATAB to A018-DATBI for valid record |
Previous Period Price/Currency | For the valid condition record get the KONP-KBETR/KONP-KONWA (For example $284/USD) |
Previous Period Price Unit/UoM | Also get the KONP-KPEIN/KONP-KMEIN (For example 100/LB) |
Yes or No value for PO Price Vs. Previous Period Price | Compare PO Net Price/Current, PO Price Unit/Ordering Price Unit with Previous Period Price/Currency and Previous Period Price Unit/UoM. If it’s matching, then Yes else No. |
Purchasing Info Record |
Pass PO number and line item to EKPO and get the EKPO- INFNR. Show that as Hyperlink and when user clicks on it, it should call T-code:ME13 (Fiori tile: Display Purchasing Info Record). Pass the PIR Number, Purchase Organization and Plant to display the record. |
Status Log | Successful/Failed message |
- After displaying output and sorting output user will select checkbox for “apply updated cost”. Program should do following:
- For selected PO & line items, it should say “Ready to update the price”? If user click YES, then go to next. If user click NO, then cancel the update.
- Upon yes, update the price on PO for that item.
- Developer can use functional module: BAPI_PO_CHANGE to update the price on PO.
- For PO change, enter the condition type: PBXX to suggest price change.
- For selected PO & line items, it should say “Ready to update the price”? If user click YES, then go to next. If user click NO, then cancel the update.
Results after Implementing solution:
Buyers click on go after entering single or multiple purchasing groups
As shown below, buyer can select one purchase order or multiple purchase orders and click on “Apply PO Cost”