03-26-2018 4:56 PM
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!
03-26-2018 10:29 PM
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
03-26-2018 10:29 PM
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
03-27-2018 5:02 PM
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...
03-27-2018 9:54 PM
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.
03-28-2018 9:55 PM
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.
03-28-2018 10:24 PM
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.
03-29-2018 12:03 PM
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 ).
03-30-2018 5:34 PM
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. 🙂