USP_REPORT_REVENUEDYNAMICS

This procedure is used as a datasource by the Revenue Dynamics Report.

Parameters

Parameter Parameter Type Mode Description
@PREVIOUSFROMDATE datetime IN
@PREVIOUSTODATE datetime IN
@THISFROMDATE datetime IN
@THISTODATE datetime IN
@DESIGNATIONID uniqueidentifier IN
@CAMPAIGNID uniqueidentifier IN
@REPORTUSERID nvarchar(128) IN
@EXCLUDEGIFTSOVER money IN
@CURRENCYCODE tinyint IN
@ALTREPORTUSERID nvarchar(128) IN

Definition

Copy


CREATE procedure dbo.USP_REPORT_REVENUEDYNAMICS
(
    @PREVIOUSFROMDATE datetime = null,
    @PREVIOUSTODATE datetime = null,
    @THISFROMDATE datetime = null,
    @THISTODATE datetime = null,
    @DESIGNATIONID uniqueidentifier = null,
    @CAMPAIGNID uniqueidentifier = null,
    @REPORTUSERID nvarchar(128) = null,
    @EXCLUDEGIFTSOVER money = 0,
    @CURRENCYCODE tinyint = null, --(null, 1) = Organization, 3 = My base

    @ALTREPORTUSERID nvarchar(128) = null
)
as
    set nocount on;

    set @EXCLUDEGIFTSOVER = coalesce(@EXCLUDEGIFTSOVER, 0);

    declare @CURRENTAPPUSERID uniqueidentifier;
    declare @ISADMIN bit;
    declare @APPUSER_IN_NONRACROLE bit;
    declare @APPUSER_IN_NOSECGROUPROLE bit;

    set @CURRENTAPPUSERID = dbo.UFN_APPUSER_GETREPORTAPPUSERID(@REPORTUSERID, @ALTREPORTUSERID);
    set @ISADMIN = dbo.UFN_APPUSER_ISSYSADMIN(@CURRENTAPPUSERID);
    set @APPUSER_IN_NONRACROLE = dbo.UFN_SECURITY_APPUSER_IN_NONRACROLE(@CURRENTAPPUSERID);
    set @APPUSER_IN_NOSECGROUPROLE = dbo.UFN_SECURITY_APPUSER_IN_NO_SECURITY_GROUP_ROLE(@CURRENTAPPUSERID);

    declare @CAMPAIGNHIERARCHYPATH hierarchyid;
    select 
        @CAMPAIGNHIERARCHYPATH=HIERARCHYPATH
    from dbo.CAMPAIGN
        where CAMPAIGN.ID = @CAMPAIGNID;

    declare @SELECTEDCURRENCYID uniqueidentifier;
    if coalesce(@CURRENCYCODE, 1) = 1
        set @SELECTEDCURRENCYID = dbo.UFN_CURRENCY_GETORGANIZATIONCURRENCY();
    else if @CURRENCYCODE = 3
        set @SELECTEDCURRENCYID = dbo.UFN_APPUSER_GETBASECURRENCY(@CURRENTAPPUSERID);

    declare @ORGANIZATIONCURRENCYID uniqueidentifier = dbo.UFN_CURRENCY_GETORGANIZATIONCURRENCY();
    declare @DECIMALDIGITS tinyint;
    declare @ROUNDINGTYPECODE tinyint;

  select 
    @DECIMALDIGITS = DECIMALDIGITS,
    @ROUNDINGTYPECODE = ROUNDINGTYPECODE
  from
    dbo.UFN_CURRENCY_GETPROPERTIES(@SELECTEDCURRENCYID);

    --JamesWill WI168303 2011-08-31 

    declare @USERREPORTSITE table 
    (
        SITEID uniqueidentifier
    );
    insert into @USERREPORTSITE(SITEID)
        select SITEID 
        from dbo.UFN_SITESFORUSERONFEATURE(@CURRENTAPPUSERID, '2a1af012-2e35-4453-9b34-ea37569f52fc', 21);

    ;with REVENUE_CTE as
    (
        select
            REVENUE.ID,
            REVENUE.CONSTITUENTID,
            sum
                (
                    case --JamesWill WI168303 2011-08-31 The report doesn't actually care about amounts before @PREVIOUSFROMDATE. It just needs to know if they 

                         --existed or not. So don't waste time converting these records. 

                        when cast(REVENUE.DATE as datetime) < @PREVIOUSFROMDATE 
                            then 1 
                        when (@SELECTEDCURRENCYID is null or @SELECTEDCURRENCYID = @ORGANIZATIONCURRENCYID
                            then REVENUESPLIT.ORGAMOUNT
                        when (@SELECTEDCURRENCYID = V.BASECURRENCYID) 
                            then REVENUESPLIT.BASEAMOUNT 
                        when [LATESTORGANIZATIONEXCHANGERATE].RATE is not null
                            then dbo.UFN_CURRENCY_ROUND(dbo.UFN_CURRENCY_APPLYRATE(REVENUESPLIT.ORGAMOUNT, [LATESTORGANIZATIONEXCHANGERATE].RATE), @DECIMALDIGITS, @ROUNDINGTYPECODE)
                        when [LATESTINVERSEORGANIZATIONEXCHANGERATE].RATE is not null
                            then dbo.UFN_CURRENCY_ROUND(dbo.UFN_CURRENCY_APPLYRATE(REVENUESPLIT.ORGAMOUNT, cast((1 / [LATESTINVERSEORGANIZATIONEXCHANGERATE].RATE) as decimal(20,8))), @DECIMALDIGITS, @ROUNDINGTYPECODE)
                        else
                            0
                    end
                 ) - case when cast(REVENUE.DATE as datetime) < @PREVIOUSFROMDATE then 0 else coalesce(sum([CREDITITEM].[TOTAL]),0) end [AMOUNT],
            cast(REVENUE.DATE as datetime) [DATE]
        from dbo.FINANCIALTRANSACTION REVENUE
        inner join dbo.REVENUE_EXT on REVENUE.ID = REVENUE_EXT.ID
        inner join dbo.FINANCIALTRANSACTIONLINEITEM REVENUESPLIT on REVENUESPLIT.FINANCIALTRANSACTIONID = REVENUE.ID
        inner join dbo.REVENUESPLIT_EXT on REVENUESPLIT.ID = REVENUESPLIT_EXT.ID
        inner join dbo.V_BASECURRENCYFORFINANCIALTRANSACTION_I V with (noexpand) on REVENUE.ID = V.FINANCIALTRANSACTIONID
        inner join dbo.UFN_SITEID_MAPFROM_REVENUESPLITID_BULK() as REVENUESITE on REVENUESITE.ID = REVENUESPLIT.ID
        outer apply
            ( 
                select 
                    0 RATE 
                where 
                    @SELECTEDCURRENCYID = @ORGANIZATIONCURRENCYID 
                    or @SELECTEDCURRENCYID = V.BASECURRENCYID
                union all
                select
                    RATE
                from
                    dbo.CURRENCYEXCHANGERATE
                where
                    @SELECTEDCURRENCYID <> @ORGANIZATIONCURRENCYID 
                    and @SELECTEDCURRENCYID <> V.BASECURRENCYID
                    and @ORGANIZATIONCURRENCYID = CURRENCYEXCHANGERATE.FROMCURRENCYID
                    and @SELECTEDCURRENCYID = CURRENCYEXCHANGERATE.TOCURRENCYID
                    and CURRENCYEXCHANGERATE.TYPECODE in (0,1)
                    and CURRENCYEXCHANGERATE.ISLATESTRATEFORASOFDATE = 1
                    and dateadd(ms, 86399996, cast(REVENUE.DATE as datetime)) >= CURRENCYEXCHANGERATE.ASOFDATESDTZ
                    and dateadd(ms, 86399996, cast(REVENUE.DATE as datetime)) <= CURRENCYEXCHANGERATE.NEXTRATEASOFDATEORMAXSDTZ
            ) LATESTORGANIZATIONEXCHANGERATE
        outer apply
            (
                select 
                    0 RATE 
                where 
                    @SELECTEDCURRENCYID = @ORGANIZATIONCURRENCYID 
                    or @SELECTEDCURRENCYID = V.BASECURRENCYID
                union all
                select
                    RATE
                from
                    dbo.CURRENCYEXCHANGERATE
                where
                    @SELECTEDCURRENCYID <> @ORGANIZATIONCURRENCYID 
                    and @SELECTEDCURRENCYID <> V.BASECURRENCYID
                    and @SELECTEDCURRENCYID = CURRENCYEXCHANGERATE.FROMCURRENCYID
                    and @ORGANIZATIONCURRENCYID= CURRENCYEXCHANGERATE.TOCURRENCYID
                    and CURRENCYEXCHANGERATE.TYPECODE in (0,1)
                    and CURRENCYEXCHANGERATE.ISLATESTRATEFORASOFDATE = 1
                    and dateadd(ms, 86399996, REVENUE.DATE) >= CURRENCYEXCHANGERATE.ASOFDATESDTZ
                    and dateadd(ms, 86399996, REVENUE.DATE) <= CURRENCYEXCHANGERATE.NEXTRATEASOFDATEORMAXSDTZ
            ) LATESTINVERSEORGANIZATIONEXCHANGERATE
        left join
            dbo.[SALESORDER] on [SALESORDER].[REVENUEID] = [REVENUE].[ID]
        left join
            dbo.[CREDIT] on [CREDIT].[SALESORDERID] = [SALESORDER].[ID]
        left join
            dbo.[CREDITITEM] on [CREDITITEM].[CREDITID] = [CREDIT].[ID]
        where REVENUE.DELETEDON is null and REVENUESPLIT.DELETEDON is null and REVENUESPLIT.TYPECODE != 1 and
            (
                (REVENUE.TYPECODE = 1) --Pledge

                or 
                (REVENUE.TYPECODE = 0 and (REVENUESPLIT_EXT.APPLICATIONCODE in (0, 4) or (REVENUESPLIT_EXT.APPLICATIONCODE = 1 and REVENUESPLIT_EXT.TYPECODE = 0) or (REVENUESPLIT_EXT.APPLICATIONCODE = 3 and REVENUESPLIT_EXT.TYPECODE <> 2))) --Payment (Gift, Other, and Recurring Gift)

                or
                (REVENUE.TYPECODE = 7) --Auction donation

                or
                ([REVENUE].TYPECODE = 5 and REVENUESPLIT_EXT.[APPLICATIONCODE] = 0 and [REVENUE].[CONSTITUENTID] is not null)  -- Order Donation w/constituent

                or
                ([REVENUE].TYPECODE = 5 and REVENUESPLIT_EXT.[APPLICATIONCODE] = 1 and REVENUESPLIT_EXT.[DESIGNATIONID] is not null)
            )
        and 
            ( @ISADMIN = 1 or (
                  (
                          @APPUSER_IN_NONRACROLE = 1 or
                          dbo.UFN_SECURITY_APPUSER_GRANTED_CONSTITID_FORREPORT(@CURRENTAPPUSERID, REVENUE.CONSTITUENTID, @APPUSER_IN_NOSECGROUPROLE) = 1
                  )
                and exists 
                    (
                        --JamesWill WI168303 2011-08-31 Check site security without using a scaler

                        select 1 from @USERREPORTSITE USERREPORTSITE
                        where USERREPORTSITE.SITEID = REVENUESITE.SITEID 
                        or (USERREPORTSITE.SITEID is null and REVENUESITE.SITEID is null)
                    )
          )

            )        
        and
            (
                (@DESIGNATIONID is null)
                or
                (REVENUESPLIT_EXT.DESIGNATIONID = @DESIGNATIONID)
            )
        and
            (
                (@CAMPAIGNID is null)
                or 
                exists (
                    select top(1)
                        REVENUESPLITCAMPAIGN.ID
                    from 
                        dbo.REVENUESPLITCAMPAIGN 
                    inner join 
                        CAMPAIGN on CAMPAIGN.ID = REVENUESPLITCAMPAIGN.CAMPAIGNID
                    where 
                        REVENUESPLITCAMPAIGN.REVENUESPLITID = REVENUESPLIT.ID 
                    and 
                        CAMPAIGN.HIERARCHYPATH.IsDescendantOf(@CAMPAIGNHIERARCHYPATH)=1
                )
            )
        and ([CREDITITEM].[TYPECODE] = 2 or [CREDITITEM].[TYPECODE] is null) --donation refunds

        group by
            REVENUE.ID, REVENUE.CONSTITUENTID, REVENUE.TYPECODE, cast(REVENUE.DATE as datetime)
    ),
    CONSTITUENTREVENUE_CTE as
    (
        select
            REVENUE_CTE.CONSTITUENTID,
            SUM(
                case
                    when (REVENUE_CTE.DATE < @PREVIOUSFROMDATE) then REVENUE_CTE.AMOUNT
                    else 0
                end        
            ) [ALLOTHERAMOUNT],
            SUM(
                case
                    when REVENUE_CTE.DATE between @PREVIOUSFROMDATE and @PREVIOUSTODATE then REVENUE_CTE.AMOUNT
                    else 0
                end
            ) [PREVIOUSPERIODAMOUNT],
            SUM(
                case 
                    when REVENUE_CTE.DATE between @THISFROMDATE and @THISTODATE then REVENUE_CTE.AMOUNT
                    else 0
                end
            ) [THISPERIODAMOUNT]
        from
            REVENUE_CTE
        where --JamesWill WI168303 2011-08-31 To avoid duplicating the currency conversion case statement from the REVENUE_CTE, I needed to bring 

              --this filter out of REVENUE_CTE and into CONSTITUENTREVENUE_CTE. This made a slight semantic change which I've documented in the bug.

            (@EXCLUDEGIFTSOVER = 0 or REVENUE_CTE.AMOUNT <= @EXCLUDEGIFTSOVER)
        group by
            REVENUE_CTE.CONSTITUENTID
    )
    select
        'http://www.blackbaud.com/CONSTITUENTID?CONSTITUENTID=' + CONVERT(nvarchar(36),CONSTITUENTREVENUE_CTE.CONSTITUENTID) as CONSTITUENTID,
        NF.NAME,
        CONSTITUENTREVENUE_CTE.PREVIOUSPERIODAMOUNT,
        CONSTITUENTREVENUE_CTE.THISPERIODAMOUNT,
        case when ALLOTHERAMOUNT > 0 then 1.0 else 0.0 end as ALLOTHERAMOUNT, --JamesWill WI168303 2011-08-31 The report doesn't actually use this value and calculating it is very expensive. But don't return an apparently random value

        case
            when THISPERIODAMOUNT > 0 and PREVIOUSPERIODAMOUNT = 0 and ALLOTHERAMOUNT = 0 then 0  --New

            when THISPERIODAMOUNT > 0 and PREVIOUSPERIODAMOUNT <= 0 and ALLOTHERAMOUNT > 0 then 1  --Recapture

            when THISPERIODAMOUNT > PREVIOUSPERIODAMOUNT and PREVIOUSPERIODAMOUNT > 0 then 2  --Upgrade

            when THISPERIODAMOUNT = PREVIOUSPERIODAMOUNT and PREVIOUSPERIODAMOUNT > 0 then 3  --Same

            when THISPERIODAMOUNT < PREVIOUSPERIODAMOUNT and THISPERIODAMOUNT <> 0 then 4 --Downgrade

            when THISPERIODAMOUNT <= 0 and PREVIOUSPERIODAMOUNT > 0 and ALLOTHERAMOUNT = 0 then 5  --Lapsed new

            when THISPERIODAMOUNT <= 0 and PREVIOUSPERIODAMOUNT > 0 and ALLOTHERAMOUNT > 0 then 6  --Lapsed repeat

        else -1 
    end [BEHAVIORTYPE]
    from
        CONSTITUENTREVENUE_CTE
    left outer join
        dbo.CONSTITUENT on CONSTITUENTREVENUE_CTE.CONSTITUENTID = CONSTITUENT.ID
    outer apply 
        dbo.UFN_CONSTITUENT_DISPLAYNAME(CONSTITUENT.ID) NF
    where
        not (PREVIOUSPERIODAMOUNT = 0 and THISPERIODAMOUNT = 0)
    order by
        CONSTITUENT.KEYNAME, CONSTITUENT.FIRSTNAME