04-30-2012 4:03 PM
We are having a problem with BAPI_SALESORDER_SIMULATE returning a price of "0" immediately after a price condition is created in VK11. Here is the sequence of events:
About one out of every three or four times, the price is coming back as "0" even though the pricing condition is created. Shouldn't the "Synchronous" option in the VK11 call ensure that the condition is saved prior to BAPI_SALESORDER_SIMULATE returns "0"? (The field that returns zero is GT_OUT-NET_VALUE1... see code below.)
ALSO NOTE: So far we are only seeing this in our production system. I wonder is multiple users using BAPI_SALESORDER_SIMULATE simultaneously could play a role in the problem.
Some key bits of code are shown below in order of execution. Please help us spot the problem if you can. Thanks!
wa_params-dismode = 'N'. "Mode 'No Display'(Mode A/E/N)
wa_params-updmode = 'S'. "synchronous Posting
wa_params-defsize = 'X'.
* ----[some unrelated screen filling code omitted]----
CONDENSE gv_fval.
PERFORM fill_bdc_data USING:
' ' 'KONP-KBETR(01)' gv_fval,
' ' 'KONP-KONWA(01)' c_unit.
CLEAR:gv_fval.
gv_fval = c_kpein.
CONDENSE gv_fval.
PERFORM fill_bdc_data USING:
' ' 'KONP-KPEIN(01)' gv_fval,
' ' 'KONP-KMEIN(01)' c_uom.
CLEAR: gv_start_date,gv_end_date,gv_date_e.
WRITE sy-datum TO gv_start_date.
gv_date_e = sy-datum + wa_material-valid.
WRITE gv_date_e TO gv_end_date.
PERFORM fill_bdc_data USING:
' ' 'RV13A-DATAB(01)' gv_start_date,
' ' 'RV13A-DATBI(01)' gv_end_date.
*--submit the mapped data to VK11 transaction
CALL TRANSACTION 'VK11' USING t_bdcdata
OPTIONS FROM wa_params
MESSAGES INTO t_mestab.
* etc....
*--subroutine excerpt
FORM GET_PRICE_OF_MATERIAL USING MATNR TYPE MATNR
MEINS TYPE MEINS
WERKS TYPE WERKS_D.
DATA : L_TABIX TYPE SY-TABIX.
CLEAR : GV_HEAD,GT_ITEM,GT_PARTNER,GV_RETURN.
REFRESH : GT_ITEM,GT_PARTNER,GT_OUT.
IF GV_VBELN IS INITIAL.
* Populate the header data for BAPI Sales Order Simulate
GV_HEAD-DOC_TYPE = 'ZPOR'.
GV_HEAD-SALES_ORG = GV_VKORG.
GV_HEAD-DISTR_CHAN = '20'.
GV_HEAD-DIVISION = 'PT'.
* here we are checking for this condition as 9999 is a vitural Branch and not
* defined in the system as real sales office.
IF GV_VKBUR = '9999'.
GV_HEAD-SALES_OFF = '4001'.
ELSE.
GV_HEAD-SALES_OFF = GV_VKBUR.
ENDIF.
GV_HEAD-REQ_DATE_H = GV_VDATU.
GV_HEAD-DATE_TYPE = '1'.
* GV_HEAD-PRICE_GRP = KONDA.
* GV_HEAD-PRICE_LIST = PLTYP.
* Populate the Partners values for the sold to and
GT_PARTNER-PARTN_ROLE = 'AG'. "SOLD TO PARTY.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = GV_SOLD_TO
IMPORTING
OUTPUT = GV_SOLD_TO.
GT_PARTNER-PARTN_NUMB = GV_SOLD_TO.
APPEND GT_PARTNER.
CLEAR GT_PARTNER.
GT_PARTNER-PARTN_ROLE = 'WE'. "SHIP TO PARTY.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = GV_SHIP_TO
IMPORTING
OUTPUT = GV_SHIP_TO.
GT_PARTNER-PARTN_NUMB = GV_SHIP_TO.
APPEND GT_PARTNER.
CLEAR GT_PARTNER.
* Populate the Items of the sales order Simulate Bapi
GT_ITEM-MATERIAL = MATNR.
GT_ITEM-REQ_QTY = 1000. " Here we want price per item hence we are passing only 1
GT_ITEM-SALES_UNIT = MEINS.
APPEND GT_ITEM.
CLEAR GT_ITEM.
* Call the Bapi Simulate funcation module to get the customer price.
CALL FUNCTION 'BAPI_SALESORDER_SIMULATE'
EXPORTING
ORDER_HEADER_IN = GV_HEAD
* CONVERT_PARVW_AUART = ' '
IMPORTING
RETURN = GV_RETURN
TABLES
ORDER_ITEMS_IN = GT_ITEM
ORDER_PARTNERS = GT_PARTNER
ORDER_ITEMS_OUT = GT_OUT. " GT_OUT-NET_VALUE1 RETURNS ZERO!!!!!????
IF GV_RETURN-TYPE <> 'E'.
*-- miscellaneous error handling...
ENDIF.
ENDFORM.
04-30-2012 6:34 PM
You make a good point about the multiple users, but don't know if that is all the problem.
Personally, I would suspect that there is sometimes a timing problem between the VK11 call and the next step. A couple of things come to mind... is the price there at some point, e.g., is it being put into the table at some point, and not lost completely? If so, I would try adding a read for the prices via Open SQL Select, perhaps with the bypassing buffer addition, to be sure that the data had made it into the tables from the VK11 call. And, you might consider adding a loop that tries x number of times, even inserting a wait up to nnn seconds if the first read fails, to be sure you retrieved a non-zero value from your pricing table before continuing to the simulate call. Sadly, that would just slow down an already slow process, but it might cure the zero value problem, which I believe is the result of updates to database not having completed before the next step from time to time, perhaps (as you mentioned) due to system load and the number of db updates queued at any one time. Would it be possible to do a commit work after the VK11 call without blowing away the process? The synchronous call success may mean only that the data has beens stored in the DB level buffer for update to the table? Have to consult the DB admins on that one.
And, I would guess that you already know that the VK11 update and the simulate are looking at the same condition table(s)? There's no chance that pricing routine is causing simulate to look at different conditions that what is expected?
04-30-2012 8:44 PM
COMMIT WORK won't do, unfortunately. Even if that works, We've been trying to squeeze every ounce of performance out of this Z-transaction. If only we could reproduce it in our QA environment. I'm glad to see you had the buffer idea. I think I'll explore more along that avenue.
Is there anything else that could more predictably cause this behavior? All ideas are welcome!
Does anyone reading this know if it's possible that a synchronous transaction call could finish WITHOUT the data actually being in the database itself, as the responder above suggests?
Thanks.
05-01-2012 3:54 PM
Actually, timing issues like this are not uncommon. I've had to insert a wait command upon occasion, due to the sheer number of tables that have to be updated for some transactions. A read inside a do ...enddo with a specific number of times, and that exits when the table is successfully read with select, seems to be the option of choice in my shop.
05-01-2012 4:23 PM
Ha! I'll give you some points for that suggestion, even though we've already done exactly that. The pricing condition is in table A506, and we are checking it 15 times in a DO loop. There seems to be plenty of time for the VK11 to finish (especially since it's marked for synchronous processing). For these ones coming back zero, obviously the loop is getting through the 15 checks with no result.
Thanks for your suggestion, though. I wonder if doing the COMMIT WORK only if the 15 loops are exhausted would be acceptable to the powers-that-be. I will run it by them.
Again, if any new readers have any suggestions, please let me know. I'll keep the thread open as long as I can.
05-01-2012 4:59 PM
Hi Case,
I'm not sure what happens here. You may check what kind of lock(s) the VK11 transaction sets (use online, check SM12).
Then, your program may try (in a loop) to set exactly this lock using ENQUEUE function until successful. Then release the lock (dequeue) and carry on. Also, the loop should terminate after a maximum time like 10 seconds or so to prohibit from endless loop because other user locks something.
And - just another possibility you may have already taken care for: Do you make sure that no errors are returned from CALL TRANSACTION 'VK11' ... INTO t_mestab. If the VK11 fails, then I would expect a price of zero.
We have positive performance results using the ENQUEUE loop technique. It also allows for asynchronuous CALL TRANSACTION which may be helpful because it will use another task. You will not need any WAIT statement which always costs more waiting time and administrative overhead triggering a UNIX sleep.
Regards
Clemens
05-01-2012 6:23 PM
Clemens,
I appreciate the idea. It's a logical idea, but for this particular lock, the lock arguments are super-duper-complex, so it would be a difficult look-up. Also, I feel like our SQL query loop of 15 times covers the same turf as looking at the locks in a much more simplified way. Thank you for your idea.