Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Zero price returned in BAPI_SALESORDER_SIMULATE for newly created price (VK11)

former_member197445
Contributor
0 Kudos

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:

  1. User executes a custom-built screen in order to create sales order line items.
  2. The material the user is entering on the sales order is not found in the database.
  3. A pop-up screen allows the user to enter the new material along with the price.
  4. Behind the scenes, when the user clicks "Save" on the new price, the material is created and the pricing condition is also created using CALL TRANSACTION 'VK11' with updmode set to 'S' fo Synchronous.
  5. After this code is finished executing, the user is returned to the main screen where BAPI_SALESORDER_SIMULATE is used to look up the newly-created price and add it to the sales order.

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.

6 REPLIES 6

Former Member
0 Kudos

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?

0 Kudos

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.

0 Kudos

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.

0 Kudos

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.

0 Kudos

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

0 Kudos

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.