ABAP log

June 16, 2008

Recoding document numbers

Filed under: ABAP, APO, SAP — abaplog @ 7:57 pm

For one of our external systems we collect the data from both R/3 and APO and last week I had an interesting problem of potential conflict between document numbers. The planned orders that are created in APO but not published to R/3 are (hopefully) guaranteed to have different document numbers than those existing in R/3. I guess you can configure the systems so that they will be using the same number range. So, if you are transferring R/3 and APO planned orders, there should not be any problems in mixing documents.

Now, imagine we have to transfer the material reservations of the planned order. If not all BOM components are known to APO, R/3 does the BOM explosion when the APO order gets published into R/3. If the order is not published, I have to make the BOM explosion in R/3 myself. How do I assign reservation numbers in a safe way? My first idea was to simply use the planned order number as reservation number abd the BOM position and the reservation position number. Wrong way. This does not ensure that the reservation numbers you “simulate” this way differ from real ones from the RESB table, because planned orders and reservations use different number ranges.

What saved me was that the reservation number for my external system doesn’t have to be purely numeric. Actually, even in R/3 itself it’s defined as “character” of length 10, and it’s only number range logic that results in numeric reservation numbers. How can we encode the numbers easily so that they will be distinct? I started looking at hexadecimal encoding. I needed to squeeze ten decimal positions into less, to save at least one position to use it as a prefix, something like “A” at the beginning, to make the resulting number (ok, not the number but “identifier”) 100% distinct. For if left just hexadecimal, we can easily have a hexadecimal number consisting just of digits, and we may end up with conflicting document numbers again.

If we split the maximum document number into two parts, i.e. two of 99999, each part can be represented with a hex number of 1869F. Same five positions! But the first one needs only one bit, it’s either zero or one! Thus, taking last four positions of both parts, and combining first two positions together into one hex digit, I can encode the whole thing into exactly nine positions, leaving one for my prefix. For example, 9999999999 will be coded like 03869F869F, and the external system will get something like A3869F869F.

The rest is the ABAP code that does the encoding:

form encode_via_hex
  using pf_char10
  changing pf_char10_out.
    lf_num51(5) type n,
    lf_hex4(4)  type x,
    lf_num1(1)   type n,
    lf_char8(8 ) type c.
  pf_char10_out = '0000000000'.
* first part
  lf_num51 = pf_char10(5).
  lf_hex4 = lf_num51.
  write lf_hex4 to lf_char8.
  lf_num1 = lf_char8+3(1) * 2.
  pf_char10_out+6(4) = lf_char8+4(4).
* second part
  lf_num51 = pf_char10+5(5).
  lf_hex4 = lf_num51.
  write lf_hex4 to lf_char8.
  lf_num1 = lf_num1 + lf_char8+3(1).
  pf_char10_out+2(4) = lf_char8+4(4).
  pf_char10_out+1(1) = lf_num1.

May 2, 2008

SAP APO Simsessions cleanup

Filed under: ABAP, APO, SAP — abaplog @ 6:56 pm

As I wrote last week, we had some problems with data not being released when making a call from R/3 to APO via RFC. I expected the data – the sumulation sessions of APO liveCache – to be cleaned up as soon as the RFC call is getting back into R/3, but they remained in memory as long as our dialog transaction on R/3 side was kept open. This was a kind of concern for our team as a problem potentially affecting liveCache performance, though in liveCache monitoring (LC10), the memory consumed by those simsessions looked quite innocent in comparison with others.

So, what was that? Whenever we want to read some liveCache data, we need to open a “session” first, for it is a required parameter to most of APO functions reading data from or writing to liveCache. Exceptions are of course BAPIs, that are dedicated to be called easily from outside. And if you are in some user exit of BADi, you don’t need the session because normally you are given one as a parameter.

So, before we start, we usually create a new session with the function /SAPAPO/RRP_SIMSESSION_CREATE. If it’s being done in a “short-living” fashion, like a report that is run and then exited, one’s sessions are gone very soon. But ours was kept open by some users, sometimes for hours. LiveCache deletes the sessions that it finds to be too old (as defined in customizing), but we wanted them to go away faster. In the same function group as CREATE function, there is the function /SAPAPO/RRP_SIMSESSION_LEAVE, but I found it to be slightly suspicious, for it is used by SAP itself only at couple of places. In addition, the code I had to fix could be calling CREATE function several times. Do I have to call LEAVE every time right after? Or are there any other ways?

I decided to search on OSS. There are many notes dealing with sessions that remain open, and I looked at how SAP solved the problem. They did it better than just calling LEAVE. Instead, before calling CREATE, they try to find any existing session created earlier in the program by calling /SAPAPO/RRP_SIMSESSION_GET. If it fails, they create a new one and set a flag (a global variable) indicating that they have to release the created session. I decided to use the same logic, so the whole sequence looked like:

*   Try to get an existing session first
    call function '/SAPAPO/RRP_SIMSESSION_GET'
        ev_simsession = lv_simsession.
    if lv_simsession is initial.
*     Create a new simsession
      call function '/SAPAPO/RRP_SIMSESSION_CREATE'
          iv_simid       = ls_params-simversion
          iv_change_mode = gc_false
          ev_simsession  = lv_simsession.
      gf_sims_created = gc_true.

* ..... now depending on program conditions,
*       follow more GET/CREATE blocks, with GET
*       most likely returning the session created earlier

* And now, cleanup:

* Did we create any sessions?
  if gf_sims_created = gc_true.
*   Check if there are any sessions still open
*   (who knows - maybe they are deleted already)
    call function '/SAPAPO/RRP_SIMSESSION_GET'
        ev_simsession = lf_simsession.
    if not lf_simsession is initial.
      call function '/SAPAPO/TSIM_SIMULATION_CANCEL'
          others = 0.
      gf_sims_created = gc_false.

Update: as our practice has shown, this way of releasing APO SIM sessions is good only if your program does exactly one RFC call to APO. If you do two, the second one will fail because APO will try to reuse the old session which is already destroyed – the result of APO keeping the data and program state from the first call and therefore some global variable not being initialized. So, in this case the right way is calling the /SAPAPO/RRP_SIMSESSION_LEAVE.

December 9, 2007

New frontiers of APO

Filed under: ABAP, APO, SAP — abaplog @ 3:26 pm

The capture of new markets by SAP flagship solutions like APO is sometimes missed by the press. But you can still discover the advances in the least expected ways.

This happened to me when the girl in our drug store offered me the best solution she had to my flu problem, earlier this year:


Well, as long as the solution is “Made in Germany”, it doesn’t hurt, right? So I decided to give it a try and I still remain very satisfied with it. After all, the cost is quite reasonable and you DO get ROI after just several days of use! (No kidding here. I normally don’t trust the homoeopathic stuff but this one works wonderfully.)

So, let me give you my advice:

If your APO makes you sick, you just need a different version. Like that one on the photo above! 

March 9, 2007

SAP APO interface (CIF): Adding new parameters into the selection screen of CFM1 (RIMODGEN)

Filed under: ABAP, APO, CIF, SAP — abaplog @ 8:26 pm

The standard transaction to generate a CIF integration model, CFM1, offers a huge set of select options, but even this has to be extended sometimes. If you need to have additional parameters on the selection screen of CFM1, OSS Note 511434 describes what has to be done. Note that the only way (and the one described in the note) is a modification of SAP code. You are going to modify the selection screen, PAI modules and function modules called by CIF. That means, during system upgrade you will have to check the source code again new changes from SAP. We went through that twice already: it’s no fun but you don’t do this often.

February 23, 2007

How to run the CIF queue LUWs that are stuck in READY state.

Filed under: ABAP, APO, CIF, SAP — abaplog @ 5:09 pm

When we started to play with SAP APO and its CIF interface with R/3, we had, as most of other companies should, all kind of data errors that brought data transfer to a halt. Normally you should clean up your data in R/3 and then run the transfer again after deleting the crashed data queue, but then we found that many queues continued to hang in WAIT state, even if the blocking entry was deleted. You can rerun those LUWs one by one manually, but it’s obviously no fun. After doing some research in OSS and asking advice on Sapfans, I have found that the program RSTRFCI3 does this for many queues at once.

Create a free website or blog at WordPress.com.