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: 

Currency conversion FM/method to rule them all?

Jelena
Active Contributor

We have a program that is using FM CONVERT_TO_FOREIGN_CURRENCY and recently ran into an issue with JPY conversion. It's a well-known problem and there are many related SCN questions (just one example).

The issue is that JPY currency is configured with "conversion factor". Current exchange rate is about 50 USD for 5000 JPY. But if FM CONVERT_TO_FOREIGN_CURRENCY (or many similar ones) is used then it returns 50 instead of 5000. The suggestions on SCN and in SAP Notes are to use BAPI_CURRENCY_CONV_TO_EXTERNAL in addition to the conversion FM to adjust the result for the factor, according to the configuration. I.e. the first FM would return 50 and then BAPI would turn it into 5000.

I've looked at some SAP correction notes and it seems that even SAP is basically doing the same: adding BAPI (or another FM) after the first FM.

My question is: is there really not a single FM or class/method that does both things? I searched using *cur*conv* mask in SE37 and SE24 but came up empty-handed. And if there is nothing like that in standard how is everyone handling this in Z code? Just call 2 FMs or a global custom method/FM?

I know this is 1001st question on the subject but it just seems odd there is still not a better standard option in 2018. Unless I'm missing something. We have ECC 6.0 EHP6 if it matters.

Thank you!

1 ACCEPTED SOLUTION

pokrakam
Active Contributor

The simplest explanation is to follow the rules: Use INTERNAL format for anything involving data type CURR. Use EXTERNAL for all other data types. Use BAPI_CURRENCY_CONV* to convert between them.

The online help explains it fairly well, but for a really detailed explanation grab a cup of coffee (you'll need it) and have a read through note 153707

7 REPLIES 7

pokrakam
Active Contributor

The simplest explanation is to follow the rules: Use INTERNAL format for anything involving data type CURR. Use EXTERNAL for all other data types. Use BAPI_CURRENCY_CONV* to convert between them.

The online help explains it fairly well, but for a really detailed explanation grab a cup of coffee (you'll need it) and have a read through note 153707

Jelena
Active Contributor
0 Kudos

Thanks for the answer, Mike! Somehow I missed that note (which really should be KBA and have a better title IMHO). Wow, forget about coffee, you need a bottle of tequila there. 🙂

I understand the part about CURR type and how it's handled. But I don't have a screen or BDC or ABAP List. It's just a utility program. All I need is to convert one number to another and there seems to be not one simple function for it already written. The note looks rather just like another "shorry, couldn't make it" from SAP. Oh well...

pokrakam
Active Contributor
0 Kudos

Regardless of screen, BDC or whatever, just apply the rule. Your number must come from somewhere, then you obviously do something with it and write/display/send it on.

If your number comes in as CURR then you work with CURRs. And if you call something that doesn't use CURR you convert to external and put the result into the target field. When you get a result back then convert to internal and put it into a CURR field. If your program output is a CURR field you can keep it internal. If it isn't, convert.

CURR = internal, else external. For any transition, switch.

Jelena
Active Contributor
0 Kudos

Thanks, Mike! I've just wrapped it up and you were right: it's just currency conversion FM in the middle wrapped between external/internal conversion. I started with just one BAPI at first and, of course, it worked for USD to JPY but then JPY to USD ended up being incorrect.

Still it's very odd that SAP didn't just write another FM (or better yet, a method) for this. I guess I'll have to put mine on abapGit or something. 🙂

Closing the question.

pokrakam
Active Contributor

Yes, BAPIs will almost always use the external format, because they are in principle supposed to be callable from the outside world.

I think the reason for all this is historic, someone had a great idea that we just treat it as integers to simplify calculations but we'll define it as a type p with two decimals so it will automatically be displayed correctly and we save the poor developers the headache of having to convert all the time. If that doesn't make sense, keep in mind that SAP started out in the 70's, an era known for recreational drug use.

luis_sismeiro
Participant
0 Kudos

Hi,

I usually retrieve the decimal places of the currency from tcurx table, and then do some math operations with the amount to convert.

Then I use BAPI BAPI_EXCHANGERATE_GETDETAIL to get the exchange rate details and use that information to do the conversion of the amount.

Example not tested.

data: ls_tcurx type tcurx,
      lv_to_curr  type SYCURR,
      lv_fr_curr  type SyCurr,
      lv_date     type sy-datum,
      lv_amount type dmbtr,
      lv_convert type dmbtr,
      ls_exchrt type bapi1093_0,
      ls_return type bapiret1.


lv_amount = 50.
lv_to_curr = 'JPY'.
lv_fr_curr = 'USD'.
lv_date = sy-datum.


select single * from tcurx into ls_tcurx
   where currkey eq lv_to_curr.
if  ls_tcurx is not initial.
case ls_tcurx-currdec.
  when 1.
    lv_amount  = lv_amount  * 10.
  when 0.
    lv_amount  = lv_amount  * 100.
  when 3.
    lv_amount  = lv_amount  / 10.
  when others.
endcase.
endif.


  call function 'BAPI_EXCHANGERATE_GETDETAIL'
    exporting
      rate_type  = '1004' " 1004 P&L / '1002' Balance Sheet
      from_curr  = lv_fr_curr
      to_currncy = lv_to_curr
      date       = '20180329'
    importing
      exch_rate  = ls_exchrt
      return     = ls_return.


    lv_convert = lv_amount  * ( ( ls_exchrt-exch_rate *  ls_exchrt-to_factor ) / ls_exchrt-from_factor ).

Well, if you look inside the internal/external conversion BAPIs you'll see they do pretty much the same thing as your code. Personally, I prefer to use standard functions whenever possible. No need to reinvent the bicycle and then be responsible for maintenance. Who knows if SAP decides to redesign the tables and what's not in S/4HANA. 🙂