UFN_CURRENCY_CONVERTBYPROPORTION

Converts an amount from one currency to another using the total amounts in both currencies.

Return

Return Type
money

Parameters

Parameter Parameter Type Mode Description
@AMOUNT money IN
@FULLAMOUNT money IN
@FULLAMOUNTTOCURRENCY money IN
@DECIMALDIGITSTOCURRENCY tinyint IN

Definition

Copy


            CREATE function dbo.UFN_CURRENCY_CONVERTBYPROPORTION
            (
                @AMOUNT money,
                @FULLAMOUNT money,
                @FULLAMOUNTTOCURRENCY money,
                @DECIMALDIGITSTOCURRENCY tinyint
            )
            returns money
            as begin
                --TODO: We could probably expand the limits but it would require more testing to find possible overflows.

                --TODO: We could probably allow negative amounts and negative full amounts but it would require more testing to find possible overflows.


                if @AMOUNT < 0 or @FULLAMOUNT < 0
                    return 0;

                if @AMOUNT >= @FULLAMOUNT
                    return @FULLAMOUNTTOCURRENCY;

                --Caution! Performing decimal math is tricky. The basic formula for @AMOUNTCONVERTED is:

                -- (@AMOUNT / @FULLAMOUNT * @FULLAMOUNTTOCURRENCY)

                -- Money fits into a decimal(19,4). Computing the amount converted percent

                -- is decimal(19,4) / decimal(19,4) = decimal(38,19). From the rule that 0 <= @AMOUNT <= @FULLAMOUNT, we

                -- know this number must be between 0 and 1 so we can reduce its precision. We convert it to

                -- decimal(22,19) so that we can multiply by @FULLAMOUNTCONVERTED without losing precision:

                -- decimal(22,19) * decimal(19,4) = decimal(38,19). Rounding to the decimal digits of the currency

                -- prevents results with fractions of pennies or fractions of yen; rounding yields smoother distributions

                -- than truncating. Finally, converting back to money removes the extra scale.


                declare @AMOUNTCONVERTEDPERCENT decimal(38,19);
                declare @AMOUNTCONVERTEDFULLPRECISION decimal(38,19);
                declare @AMOUNTCONVERTED money;

                set @AMOUNTCONVERTEDPERCENT = (convert(decimal(19,4),(@AMOUNT)) / convert(decimal(19,4),@FULLAMOUNT));
                set @AMOUNTCONVERTEDFULLPRECISION = (convert(decimal(22,19),@AMOUNTCONVERTEDPERCENT) * convert(decimal(19,4),@FULLAMOUNTTOCURRENCY));
                set @AMOUNTCONVERTED = convert(money, round(@AMOUNTCONVERTEDFULLPRECISION, @DECIMALDIGITSTOCURRENCY, 0));

                if @AMOUNTCONVERTED > @FULLAMOUNTTOCURRENCY
                    set @AMOUNTCONVERTED = @FULLAMOUNTTOCURRENCY;

                return @AMOUNTCONVERTED;
            end