UFN_CURRENCY_GETCURRENCYVALUESBYPROPORTIONINXML

Converts amounts in XML from a transaction currency to a base and organization currency, based on the proportions of their respective totals to each other.

Return

Return Type
table

Parameters

Parameter Parameter Type Mode Description
@ITEMLIST xml IN
@TRANSACTIONCURRENCYID uniqueidentifier IN
@BASECURRENCYID uniqueidentifier IN
@ORGANIZATIONCURRENCYID uniqueidentifier IN
@FULLAMOUNTTRANSACTIONCURRENCY money IN
@FULLAMOUNTBASECURRENCY money IN
@DECIMALDIGITSBASECURRENCY int IN
@FULLAMOUNTORGANIZATIONCURRENCY money IN
@DECIMALDIGITSORGANIZATIONCURRENCY int IN

Definition

Copy


            CREATE function dbo.UFN_CURRENCY_GETCURRENCYVALUESBYPROPORTIONINXML(
                @ITEMLIST xml,
                @TRANSACTIONCURRENCYID uniqueidentifier,
                @BASECURRENCYID uniqueidentifier,
                @ORGANIZATIONCURRENCYID uniqueidentifier,
                @FULLAMOUNTTRANSACTIONCURRENCY money,
                @FULLAMOUNTBASECURRENCY money,
                @DECIMALDIGITSBASECURRENCY int,
                @FULLAMOUNTORGANIZATIONCURRENCY money,
                @DECIMALDIGITSORGANIZATIONCURRENCY int
            ) 
            returns table
            as 
            return(

                ------

                -- This function will take a properly formatted XML parameter, and various currency information 

                --    and return a table containing the correct base and org amount for each row in the XML.  This

                --    is a 5 step process:

                --    0)    The ITEMLIST XML must consist of a single root element that contains ITEM elements.

                --        Each ITEM element must contain a single AMOUNT element.  The value in this AMOUNT element

                --        is treated as the transaction amount for the row.  All other elements in the ITEM element

                --        are ignored, though they will be passed out in the ITEM column in the returned table.

                --    1)    Build a table with a row for each item in the ITEMLIST XML parameter.  Each row will have

                --        a column for an assigned row number, a column for the AMOUNT value, and a column to contain

                --        the ITEM element the row represents.

                --    2)    Given a row number and a transaction amount for each item, calculate a running total in

                --        the base currency.

                --    3)    Given a row number and base running total, subtract each successive total to get a base

                --        amount for the row.  We also incorporate info about the origin of the org amount here, for

                --        use by steps 4 and 5.

                --    4)  Given a row number, transaction amount, base amount, and origin info, calculate a running 

                --        total in the organization currency.

                --    5)    Given a row number, organization running total, and origin info, subtract each successive

                --        total to get an organization amount for each row.



                with CTE_ITEMLIST as ( --Generate row numbers and amounts for each item in the given list.

                    select
                        ITEMNUMBER.ROW,
                        ITEMLIST.ITEM.query('(ITEM[position() = sql:column("ITEMNUMBER.ROW")])[1]') ITEM,
                        ITEMLIST.ITEM.value('(ITEM[position() = sql:column("ITEMNUMBER.ROW")]/AMOUNT)[1]','money') AMOUNT
                    from @ITEMLIST.nodes('/*') ITEMLIST(ITEM)
                        cross join (
                            select
                                row_number() over (order by ITEMLIST.ITEM) ROW
                            from
                                @ITEMLIST.nodes('/*/ITEM') ITEMLIST(ITEM)
                        ) ITEMNUMBER
                ),
                CTE_ITEMBASERUNNINGTOTAL as ( --Calculate the running total for the base amount.

                    select
                        ROW,
                        ITEM,
                        AMOUNT,
                        case  --If transaction currency equals base currency, no conversion is necessary.

                            when @TRANSACTIONCURRENCYID <> @BASECURRENCYID
                                --If currencies are different, use a proportional running total based on trans full amount.

                                then dbo.UFN_CURRENCY_CONVERTBYPROPORTION(
                                        (
                                            select sum(ALLPREVIOUSITEMAMOUNT.AMOUNT) 
                                            from CTE_ITEMLIST ALLPREVIOUSITEMAMOUNT 
                                            where ALLPREVIOUSITEMAMOUNT.ROW <= ITEMLIST.ROW
                                        ),
                                        @FULLAMOUNTTRANSACTIONCURRENCY,
                                        @FULLAMOUNTBASECURRENCY,
                                        @DECIMALDIGITSBASECURRENCY
                                    )
                            else --Otherwise, just use the trans amount 

                                AMOUNT
                        end BASEAMOUNTORRUNNINGTOTAL
                    from CTE_ITEMLIST as ITEMLIST
                ),
                CTE_ITEMBASEAMOUNT as (    --Calculate the actual base amounts.

                    select
                        ROW,
                        ITEM,
                        AMOUNT,
                        case
                            when @TRANSACTIONCURRENCYID <> @BASECURRENCYID
                                --If currencies are different, we know a proportional running total was created above, so 

                                --    do subtraction here.

                                 then ITEMBASERUNNINGTOTAL.BASEAMOUNTORRUNNINGTOTAL 
                                    - coalesce(
                                        (
                                            select PREVIOUSCONVERTEDRUNNINGTOTAL.BASEAMOUNTORRUNNINGTOTAL
                                            from CTE_ITEMBASERUNNINGTOTAL as PREVIOUSCONVERTEDRUNNINGTOTAL
                                            where PREVIOUSCONVERTEDRUNNINGTOTAL.ROW = ITEMBASERUNNINGTOTAL.ROW - 1
                                        )
                                        ,0
                                    )
                             else  --Otherwise, we know the "running total" is really just the trans amount, so no math needed.

                                ITEMBASERUNNINGTOTAL.BASEAMOUNTORRUNNINGTOTAL
                        end BASEAMOUNT,
                        BASEAMOUNTORRUNNINGTOTAL,
                        ORGANIZATIONORIGIN.ORGANIZATIONAMOUNTORIGINCODE,
                        ORGANIZATIONORIGIN.ORGANIZATIONEQUALSTRANSACTIONCURRENCY,
                        ORGANIZATIONORIGIN.ORGANIZATIONEQUALSBASECURRENCY
                    from CTE_ITEMBASERUNNINGTOTAL as ITEMBASERUNNINGTOTAL
                        cross join( --Join in info about the organization amount origin for use in later CTEs.

                            select    
                                coalesce(
                                    (
                                        select top 1 ORGANIZATIONAMOUNTORIGINCODE 
                                        from dbo.MULTICURRENCYCONFIGURATION
                                    )
                                    ,0
                                ) ORGANIZATIONAMOUNTORIGINCODE,
                                case
                                    when dbo.UFN_CURRENCY_GETORGANIZATIONCURRENCY() = @TRANSACTIONCURRENCYID
                                        then 1
                                    else 0
                                end ORGANIZATIONEQUALSTRANSACTIONCURRENCY,
                                case
                                    when dbo.UFN_CURRENCY_GETORGANIZATIONCURRENCY() = @BASECURRENCYID
                                        then 1
                                    else 0
                                end ORGANIZATIONEQUALSBASECURRENCY
                        ) ORGANIZATIONORIGIN
                ),
                CTE_ITEMORGANIZATIONRUNNINGTOTAL as ( --Calculate running total for the organization amount.

                    select
                        ROW,
                        ITEM,
                        AMOUNT,
                        BASEAMOUNT,
                        BASEAMOUNTORRUNNINGTOTAL,
                        case  --Consider org amount origin when calculating running total.

                            when ORGANIZATIONAMOUNTORIGINCODE = 1 and ORGANIZATIONEQUALSTRANSACTIONCURRENCY = 0
                                --Using trans amount to calc org amount, but currencies don't match, so use a proportional running 

                                --    total based on trans full amount.

                                then dbo.UFN_CURRENCY_CONVERTBYPROPORTION(
                                        (
                                            select sum(ALLPREVIOUSITEMORGAMOUNT.AMOUNT) 
                                            from CTE_ITEMBASEAMOUNT as ALLPREVIOUSITEMORGAMOUNT 
                                            where ALLPREVIOUSITEMORGAMOUNT.ROW <= ITEMLIST.ROW
                                        ),
                                        @FULLAMOUNTTRANSACTIONCURRENCY,
                                        @FULLAMOUNTORGANIZATIONCURRENCY,
                                        @DECIMALDIGITSORGANIZATIONCURRENCY
                                    )        
                            when ORGANIZATIONAMOUNTORIGINCODE = 1 and ORGANIZATIONEQUALSTRANSACTIONCURRENCY = 1
                                --Using trans amount to calc org amount and currencies do match, so just put in the trans amount.

                                then AMOUNT         
                            when ORGANIZATIONAMOUNTORIGINCODE = 0 and ORGANIZATIONEQUALSBASECURRENCY = 0
                                --Using base amount to calc org amount, but currencies don't match, so use a proportional running 

                                --    total based on base full amount.

                                then dbo.UFN_CURRENCY_CONVERTBYPROPORTION(
                                        (
                                            select sum(ALLPREVIOUSITEMORGAMOUNT.BASEAMOUNT) 
                                            from CTE_ITEMBASEAMOUNT as ALLPREVIOUSITEMORGAMOUNT 
                                            where ALLPREVIOUSITEMORGAMOUNT.ROW <= ITEMLIST.ROW
                                        ),
                                        @FULLAMOUNTBASECURRENCY,
                                        @FULLAMOUNTORGANIZATIONCURRENCY,
                                        @DECIMALDIGITSORGANIZATIONCURRENCY
                                    )
                            when ORGANIZATIONAMOUNTORIGINCODE = 0 and ORGANIZATIONEQUALSBASECURRENCY = 1
                                --Using base amount to calc org amount and currencies do match, so just put in the base amount.

                                then BASEAMOUNT
                        end ORGANIZATIONAMOUNTORRUNNINGTOTAL,
                        ORGANIZATIONAMOUNTORIGINCODE,
                        ORGANIZATIONEQUALSTRANSACTIONCURRENCY,
                        ORGANIZATIONEQUALSBASECURRENCY
                    from CTE_ITEMBASEAMOUNT as ITEMLIST
                )
                select --Calculate the actual organization amounts and return the other information needed.

                    ROW,
                    ITEM, 
                    BASEAMOUNT,
                    case
                        when (ORGANIZATIONAMOUNTORIGINCODE = 1 and ORGANIZATIONEQUALSTRANSACTIONCURRENCY = 0)
                                or (ORGANIZATIONAMOUNTORIGINCODE = 0 and ORGANIZATIONEQUALSBASECURRENCY = 0)
                            --If org currency doesn't match the currency of the currency of the origin amount, we know a proportional 

                            --    running total was created above, so do subtraction here.

                            then ITEMRUNNINGTOTAL.ORGANIZATIONAMOUNTORRUNNINGTOTAL
                                - coalesce(
                                    (
                                        select PREVIOUSCONVERTEDORGANIZATIONRUNNINGTOTAL.ORGANIZATIONAMOUNTORRUNNINGTOTAL
                                        from CTE_ITEMORGANIZATIONRUNNINGTOTAL as PREVIOUSCONVERTEDORGANIZATIONRUNNINGTOTAL
                                        where PREVIOUSCONVERTEDORGANIZATIONRUNNINGTOTAL.ROW = ITEMRUNNINGTOTAL.ROW - 1
                                    )
                                    ,0
                                )
                        else --Otherwise, we know the "running total" is really just the desired amount, so no math needed. 

                            ITEMRUNNINGTOTAL.ORGANIZATIONAMOUNTORRUNNINGTOTAL 
                    end ORGANIZATIONAMOUNT
                from CTE_ITEMORGANIZATIONRUNNINGTOTAL as ITEMRUNNINGTOTAL

            );