Enterprise Resource Planning Blogs by Members
Gain new perspectives and knowledge about enterprise resource planning in blog posts from community members. Share your own comments and ERP insights today!
cancel
Showing results for 
Search instead for 
Did you mean: 
suresh_kutam
Participant

Scenario


Service PO creation / change scenario – Service Quantity increasing more than requested in PR.

If we are creating PO with respective to RFQ, we can increase the any service line item quantity whatever we wanted. There is no proper SAP validation exist in PO for the POs which are created with reference to RFQ. This scenario is related to only service POs.

Steps for replication

Create PR with multiple service line items,

Example,

  1. Service line item keep the quantity as “100” for any line item (in this case consider I have 2nd service line item quantity as “100”.

  2. Release the PR.

  3. Create RFQ with reference to PR and release RFQ.

  4. Now create PO with reference to RFQ created in Step 3, where PR number will be auto populated from RFQ. Now save the PO.

    • Now come back to the same PO which is created in step 4, change 2nd service line item quantity to 200 or 300 or whatever number you want. System will not stop you.

    • Other scenario is in first PO it is 100 quantity, now I will create another PO with same RFQ and quantity would be populated with 100. Try to save now it will allow us to save even though we are creating multiple POs with more than requested PR Quantity.




 

Reason is actually quantity field is not updated in the PRs for the POs created using RFQ. And its more complex as it deals with pack no and sub pack numbers.

 

For some of the business this is key validation as PR quantity must validate during the PO creation.

 

Solution::-

Used BADI “ME_PROCESS_PO_CUST” implementation and method "Check" where it will validate PO items.

Implement below logic -

 
Declarations -

TYPES:
lty_t_esll TYPE STANDARD TABLE OF esll WITH DEFAULT KEY.

TYPES:
*// To read PR details and its package number
BEGIN OF ty_eban,
banfn TYPE banfn,
bnfpo TYPE bnfpo,
bsart TYPE bbsrt,
loekz TYPE eloek,
packno TYPE packno,
END OF ty_eban,

BEGIN OF ty_esll,
packno TYPE packno,
introw TYPE numzeile,
srvpos TYPE asnum,
sub_packno TYPE sub_packno,
menge TYPE mengev,
END OF ty_esll,

*// To get all POs which are used this PR and line item
BEGIN OF ty_ekpo_val,
ebeln TYPE ebeln,
ebelp TYPE ebelp,
loekz TYPE eloek,
banfn TYPE banfn,
bnfpo TYPE bnfpo,
packno TYPE packno,
END OF ty_ekpo_val.

FIELD-SYMBOLS:
<lfs_lw_esll_sub> TYPE esll.

DATA:
lv_err_flg TYPE char1,
lv_srv_nt_pr TYPE char1,
lv_curr_po_qty TYPE mengev,
lv_pr_qty TYPE mengev,
lv_bal_qty TYPE mengev,
lv_pr_qty_by TYPE mengev,
lv_bal_qtyc TYPE char20,
lv_pr_qty_byc TYPE char20,
lv_cur_ser_qtyc TYPE char20,
lv_exis_po_qty TYPE mengev,
lv_cur_ser_qty TYPE mengev,
lv_new_po_qty TYPE mengev,
lv_extrow TYPE extrow,
lv_ebelps TYPE ebelp,
lv_service TYPE asnum,
lt_ekpo_val TYPE STANDARD TABLE OF ty_ekpo_val INITIAL SIZE 0,
lw_ekpo_val TYPE ty_ekpo_val,
lt_items_tmp TYPE TABLE OF mepoitem,
lt_items_ser TYPE TABLE OF mepoitem,
lt_items_ser_tmp TYPE TABLE OF mepoitem,
lw_items_ser_tmp TYPE mepoitem,
lw_items_ser TYPE mepoitem,
ls_item TYPE meout_item,
lr_esll TYPE REF TO esll,
ls_srv TYPE if_mmbsi_gui_factory=>type_s_srv_key,
lt_esll_sub TYPE lty_t_esll,
lt_esll_loop TYPE lty_t_esll,
lw_esll_loop TYPE esll,
lt_esll TYPE lty_t_esll,
lw_eban TYPE ty_eban,
lt_eban TYPE STANDARD TABLE OF ty_eban INITIAL SIZE 0,
lt_esll_pr TYPE STANDARD TABLE OF ty_esll INITIAL SIZE 0,
lw_esll_pr TYPE ty_esll,
lw_esll_subpack TYPE ty_esll,
lt_esll_subpack TYPE STANDARD TABLE OF ty_esll INITIAL SIZE 0,
lt_esll_popack TYPE STANDARD TABLE OF ty_esll INITIAL SIZE 0,
lw_esll_popack TYPE ty_esll,
lw_esll_posubp TYPE ty_esll,
lt_esll_posubp TYPE STANDARD TABLE OF ty_esll INITIAL SIZE 0,
lt_esll_curpac TYPE lty_t_esll,
lt_esll_cursubp TYPE lty_t_esll,
lw_esll_cursubp TYPE esll.


CALL METHOD im_header->if_dcm_adapter~get_manager
RECEIVING
re_mgr = re_mgr.

IF re_mgr IS BOUND.
CALL METHOD re_mgr->get_current_item
RECEIVING
re_item = re_item.
ENDIF.

IF re_item IS BOUND.
CALL METHOD re_item->get_data
RECEIVING
re_data = re_data.
ENDIF.

CALL METHOD im_header->get_items
RECEIVING
re_items = re_items.

LOOP AT re_items INTO wa_items.
CALL METHOD wa_items-item->get_data
RECEIVING
re_data = re_idata.

APPEND re_idata TO ist_items.

ENDLOOP.

REFRESH:
lt_esll_curpac,
lt_esll_cursubp,
lt_eban,
lt_esll_pr,
lt_esll_subpack,
lt_ekpo_val,
lt_items_ser,
lt_items_tmp.


*// consider only service line item for validation...
APPEND LINES OF ist_items TO lt_items_ser.
DELETE lt_items_ser WHERE pstyp NE '9'.
*// If we have entered PR only - it must valiate
*// IF PR is not entered do not required to validate..
DELETE lt_items_ser WHERE banfn IS INITIAL.
*// Do not considere delete (marked) line items
DELETE lt_items_ser WHERE loekz IS NOT INITIAL.

*// At least one service line item must exist..
CLEAR:
lw_items_ser.

READ TABLE lt_items_ser INTO lw_items_ser INDEX 1.
IF sy-subrc IS INITIAL.

*// Get unique PR and PR line item number to get all the POs,
*// which are already used these PR&PR line items
APPEND LINES OF lt_items_ser TO lt_items_tmp.
SORT lt_items_tmp BY banfn bnfpo.
DELETE ADJACENT DUPLICATES FROM lt_items_tmp
COMPARING banfn bnfpo.

*// Get the selected PRs and its line item details -> GET PACK number to read all service lines
*// under that PR line items
IF lt_items_tmp IS NOT INITIAL.

SELECT
banfn
bnfpo
bsart
loekz
packno
FROM eban
INTO TABLE lt_eban
FOR ALL ENTRIES IN lt_items_tmp
WHERE banfn = lt_items_tmp-banfn
AND bnfpo = lt_items_tmp-bnfpo.
IF sy-subrc IS INITIAL.
SORT lt_eban BY banfn bnfpo.
ENDIF.

IF lt_eban IS NOT INITIAL.
*// Get PR package number
SELECT
packno
introw
srvpos
sub_packno
menge
FROM esll
INTO TABLE lt_esll_pr
FOR ALL ENTRIES IN lt_eban
WHERE packno EQ lt_eban-packno.
IF sy-subrc IS INITIAL.
SORT lt_esll_pr BY packno.
*// Get PR sub package number, where you will have activity/service number

SELECT
packno
introw
srvpos
sub_packno
menge
FROM esll
INTO TABLE lt_esll_subpack
FOR ALL ENTRIES IN lt_esll_pr
WHERE packno EQ lt_esll_pr-sub_packno.
IF sy-subrc IS INITIAL.
SORT lt_esll_subpack BY sub_packno.
ENDIF.

ENDIF.

ENDIF.

*// Get all PO detals from PR
SELECT
ebeln
ebelp
loekz
banfn
bnfpo
packno
FROM ekpo
INTO TABLE lt_ekpo_val
FOR ALL ENTRIES IN lt_items_tmp
WHERE loekz = space
AND banfn = lt_items_tmp-banfn
AND bnfpo = lt_items_tmp-bnfpo.
IF sy-subrc IS INITIAL.
*// Delete PO details of current PO
DELETE lt_ekpo_val WHERE ebeln = lw_items_ser-ebeln.
SORT lt_ekpo_val BY packno.
ENDIF.

*// Get PO line items pack number
IF lt_ekpo_val IS NOT INITIAL.

SELECT
packno
introw
srvpos
sub_packno
menge
FROM esll
INTO TABLE lt_esll_popack
FOR ALL ENTRIES IN lt_ekpo_val
WHERE packno EQ lt_ekpo_val-packno.
IF sy-subrc IS INITIAL.
*// Get PO line item sub pack number
SELECT
packno
introw
srvpos
sub_packno
menge
FROM esll
INTO TABLE lt_esll_posubp
FOR ALL ENTRIES IN lt_esll_popack
WHERE packno EQ lt_esll_popack-sub_packno.
IF sy-subrc IS INITIAL.
SORT lt_esll_posubp BY sub_packno.
ENDIF.
ENDIF.
ENDIF.
ENDIF.

******************************************************
*// Read current PO line item services details
******************************************************
*// Take unique PR and line items to process the validation
REFRESH:
lt_items_ser_tmp.

APPEND LINES OF lt_items_ser TO lt_items_ser_tmp.
SORT lt_items_ser_tmp BY banfn bnfpo.
DELETE ADJACENT DUPLICATES FROM lt_items_ser_tmp
COMPARING banfn bnfpo.

CLEAR:
lv_err_flg,
lw_items_ser_tmp,
wa_items_final.

LOOP AT lt_items_ser_tmp INTO lw_items_ser_tmp.

CLEAR:
wa_items_final.

REFRESH:
lt_esll_cursubp.

LOOP AT lt_items_ser INTO wa_items_final
WHERE banfn = lw_items_ser_tmp-banfn
AND bnfpo = lw_items_ser_tmp-bnfpo.

REFRESH:
lt_esll_loop,
lt_esll.

*// read esll data, as it is not available in my_items
CALL FUNCTION 'MS_READ_SERVICES'
EXPORTING
i_packno = wa_items_final-packno
TABLES
t_esll = lt_esll.

APPEND LINES OF lt_esll TO lt_esll_curpac.

*// Get SUB PACK for this package..
LOOP AT lt_esll REFERENCE INTO lr_esll.
REFRESH:
lt_esll_sub.

*//read esll for sub_packno
CLEAR lt_esll_sub.
CALL FUNCTION 'MS_READ_SERVICES'
EXPORTING
i_packno = lr_esll->sub_packno
TABLES
t_esll = lt_esll_sub.

APPEND LINES OF lt_esll_sub TO lt_esll_cursubp.
APPEND LINES OF lt_esll_sub TO lt_esll_loop.
ENDLOOP. "LOOP AT lt_esll REFERENCE INTO lr_esll.

REFRESH:
lt_esll_sub.
APPEND LINES OF lt_esll_cursubp TO lt_esll_sub.

***********************/******************************
*// PO loaded data..
*// Check each service line qty - in case if the service line is repeated
*// take the consolidated qty to compare PR qty
***********************/******************************
CLEAR:
lw_esll_loop.
*// loop only current line item services to compare the values
LOOP AT lt_esll_loop INTO lw_esll_loop
WHERE srvpos IS NOT INITIAL.

UNASSIGN:
<lfs_lw_esll_sub>.

READ TABLE lt_esll_sub ASSIGNING <lfs_lw_esll_sub>
WITH KEY srvpos = lw_esll_loop-srvpos.
IF sy-subrc IS INITIAL.

CLEAR:
lv_curr_po_qty,
lv_pr_qty,
lv_cur_ser_qty,
lv_exis_po_qty,
lv_ebelps,
lv_extrow,
lv_service.


lv_extrow = lw_esll_loop-extrow. "Current service line item#
lv_service = lw_esll_loop-srvpos. "Current Service number
lv_ebelps = wa_items_final-ebelp.
SHIFT lv_ebelps LEFT DELETING LEADING c_0.
SHIFT lv_extrow LEFT DELETING LEADING c_0.
SHIFT lv_service LEFT DELETING LEADING c_0.

lv_cur_ser_qty = lw_esll_loop-menge.
*// Service line item total qty in current PO
LOOP AT lt_esll_cursubp INTO lw_esll_cursubp
WHERE srvpos = <lfs_lw_esll_sub>-srvpos.
*// Get Service qty till the current line for accurate results on error message
IF lw_esll_cursubp-introw > lw_esll_loop-introw.
EXIT.
ENDIF.
lv_curr_po_qty = lw_esll_cursubp-menge + lv_curr_po_qty.
ENDLOOP.


*// service line item qty in PR
CLEAR:
lv_srv_nt_pr,
lw_eban.
LOOP AT lt_eban INTO lw_eban
WHERE banfn = wa_items_final-banfn
AND bnfpo = wa_items_final-bnfpo.

*// Get PR pack number
CLEAR:
lw_esll_pr.
READ TABLE lt_esll_pr
INTO lw_esll_pr
WITH KEY packno = lw_eban-packno.
IF sy-subrc IS INITIAL.
CLEAR:
lw_esll_subpack.
LOOP AT lt_esll_subpack INTO lw_esll_subpack
WHERE packno = lw_esll_pr-sub_packno
AND srvpos = <lfs_lw_esll_sub>-srvpos.
lv_pr_qty = lw_esll_subpack-menge + lv_pr_qty.
lv_srv_nt_pr = abap_true.
ENDLOOP.
ENDIF.
ENDLOOP. "service line item qty in PR

IF lv_srv_nt_pr IS INITIAL.
CLEAR:
lv_message,
lv_message1.

lv_err_flg = abap_true.
CONCATENATE
'For line item' lv_ebelps
'service line' lv_extrow
'/' lv_service '-'
INTO
lv_message SEPARATED BY space.


lv_message1 = 'Service line not existing in PR'.

mmpur_message_forced 'E' 'ME' '303' lv_message lv_message1 space space.

ELSE.
*// service line item qty in existing/already created POs
CLEAR:
lw_ekpo_val.
LOOP AT lt_ekpo_val INTO lw_ekpo_val
WHERE banfn = wa_items_final-banfn
AND bnfpo = wa_items_final-bnfpo.

CLEAR:
lw_esll_popack.

READ TABLE lt_esll_popack
INTO lw_esll_popack
WITH KEY packno = lw_ekpo_val-packno.
IF sy-subrc IS INITIAL.
LOOP AT lt_esll_posubp INTO lw_esll_posubp
WHERE packno = lw_esll_popack-sub_packno
AND srvpos = <lfs_lw_esll_sub>-srvpos.
lv_exis_po_qty = lv_exis_po_qty + lw_esll_posubp-menge.
ENDLOOP.
ENDIF.
ENDLOOP. "service line item qty in existing/already created POs

CLEAR:
lv_new_po_qty.

*// All values exist - Compare and calculate...
*// If not add new PO service line qty and see if it exceeds again
lv_new_po_qty = lv_curr_po_qty + lv_exis_po_qty.

IF lv_new_po_qty > lv_pr_qty.
*// New Service Qty is exceeding the PR qty.
lv_err_flg = abap_true.
<lfs_lw_esll_sub>-menge = lv_pr_qty - lv_exis_po_qty.

CLEAR:
lv_message,
lv_message1,
lv_bal_qty,
lv_pr_qty_by,
lv_bal_qtyc,
lv_cur_ser_qtyc,
lv_pr_qty_byc,
lv_message2,
lv_message3.

lv_bal_qty = lv_pr_qty - lv_exis_po_qty.
lv_pr_qty_by = lv_curr_po_qty - lv_bal_qty.
*// To use in concatenate for error message
lv_bal_qtyc = lv_bal_qty.
*// Since it is cumulating the values - balance should be shown less than current
IF lv_pr_qty_by <= lv_cur_ser_qty.
lv_pr_qty_byc = lv_pr_qty_by.
ELSE.
lv_pr_qty_byc = lv_cur_ser_qty.
ENDIF.
lv_cur_ser_qtyc = lv_cur_ser_qty.


*‘Quantity XXXX (this is entered quantity) exceeds target quantity yyyy (balance quantity available)
*for the Purchase req. by ZZZZ (Difference of XXXX and yyyyy)’

CONCATENATE
'For line item' lv_ebelps
'service line' lv_extrow
'/' lv_service '-'
INTO
lv_message SEPARATED BY space.

CONCATENATE
'Quantity exceeds by' lv_pr_qty_byc
INTO
lv_message1 SEPARATED BY space.

CONCATENATE
'for entered quantity'
lv_cur_ser_qtyc
INTO
lv_message2 SEPARATED BY space.


CONCATENATE
'as balance PR Qty is'
lv_bal_qtyc
INTO
lv_message3 SEPARATED BY space.

mmpur_message_forced 'E' 'ME' '303' lv_message lv_message1 lv_message2 lv_message3.
ELSE.
*// do nothing
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDLOOP. "LOOP AT lt_items_ser INTO wa_items_final.
ENDLOOP. "For unique PR & PR line item

IF lv_err_flg IS NOT INITIAL.
ch_failed = 'X'.
ENDIF.

ENDIF. "At least one service line item must exist..

 

 

Thanks,

Suresh Kutam
2 Comments