UFN_REVENUE_GETNEXTTRANSACTIONDATE_BYID_1_1

Returns the next transaction date for a recurring gift. If @ASOFDATE is null, the current NEXTTRANSACTIONDATE will be used.

Return

Return Type
datetime

Parameters

Parameter Parameter Type Mode Description
@REVENUEID uniqueidentifier IN
@ASOFDATE datetime IN

Definition

Copy


            CREATE function dbo.UFN_REVENUE_GETNEXTTRANSACTIONDATE_BYID_1_1
            (
                @REVENUEID uniqueidentifier,
                @ASOFDATE datetime
            )
            returns datetime
            as
            begin
                declare @STARTDATE datetime;
                declare @FREQUENCYCODE tinyint;
                declare @NEXTTRANSACTIONDATE datetime;
                declare @ISLASTDAYOFMONTH bit;

                select
                    @STARTDATE = case when SCHEDULESEEDDATE > STARTDATE and SCHEDULESEEDDATE > NEXTTRANSACTIONDATE then dbo.UFN_DATE_GETEARLIESTTIME(coalesce(NEXTTRANSACTIONDATE, SCHEDULESEEDDATE)) else dbo.UFN_DATE_GETEARLIESTTIME(coalesce(SCHEDULESEEDDATE, STARTDATE)) end,
                    @FREQUENCYCODE = FREQUENCYCODE,
                    @NEXTTRANSACTIONDATE = dbo.UFN_DATE_GETEARLIESTTIME(coalesce(@ASOFDATE, NEXTTRANSACTIONDATE))
                from dbo.REVENUESCHEDULE
                where ID = @REVENUEID;

                declare @DAYSINSTARTMONTH tinyint;
                declare @STARTMONTH tinyint;
                declare @STARTYEAR smallint;
                declare @STARTDAY tinyint;

                select
                    @STARTMONTH = datepart(month, @STARTDATE),
                    @STARTYEAR = datepart(year, @STARTDATE),
                    @STARTDAY = datepart(day, @STARTDATE)

                set @DAYSINSTARTMONTH = dbo.UFN_DAYSINMONTH(@STARTMONTH, @STARTYEAR)
                select 
                    @ISLASTDAYOFMONTH = case when @STARTDAY >= @DAYSINSTARTMONTH then 1 else 0 end;

                declare @POTENTIALDATE datetime;
                set @POTENTIALDATE = @STARTDATE;

                -- counter for number of skipped monthly installments

                declare @NUMSKIPPEDINSTALLMENTS int;
                set @NUMSKIPPEDINSTALLMENTS = 0;

                while @POTENTIALDATE <= @NEXTTRANSACTIONDATE
                begin
                    if @FREQUENCYCODE = 0 --Annually

                        set @POTENTIALDATE = dateadd(year, 1, @POTENTIALDATE);
                    else if @FREQUENCYCODE = 1 --Semi-annually

                        set @POTENTIALDATE = dateadd(month, 6, @POTENTIALDATE);
                    else if @FREQUENCYCODE = 2 --Quarterly

                        set @POTENTIALDATE = dateadd(quarter, 1, @POTENTIALDATE);
                    else if @FREQUENCYCODE = 3 --Monthly

                    begin
                        -- increment counter then add counter number of months to original start date

                        -- incrementing from start date keeps the day part the same (except for short months)

                        set @NUMSKIPPEDINSTALLMENTS = @NUMSKIPPEDINSTALLMENTS + 1;

                    declare @ISCONFIGURABLE bit;

                    select TOP 1 @ISCONFIGURABLE = 1
                    from APPSETTING
                    where NAME = 'RGSCHEDULECONFIGURABLEDATE' AND VALUE = 1;

                    -- Set default if no match found

                    if @ISCONFIGURABLE is NULL set @ISCONFIGURABLE = 0;

                    if @ISCONFIGURABLE = 0
                    begin
                        if eomonth(@STARTDATE) = @STARTDATE  
                            set @POTENTIALDATE = eomonth(@STARTDATE, @NUMSKIPPEDINSTALLMENTS);  
                        else
                            set @POTENTIALDATE = dateadd(month, @NUMSKIPPEDINSTALLMENTS, @STARTDATE);  
                    end
                else
                begin
                    -- precompute once, outside if conditions

                        declare @NEXTMONTHDATE date = dateadd(month, @NUMSKIPPEDINSTALLMENTS, @STARTDATE);
                        declare @DAY int = day(@STARTDATE);
                        declare @ISFEBEND bit = iif(month(@STARTDATE) = 2 and @DAY in (28, 29), 1, 0);
                        declare @MAXDAYOFTARGETMONTH int = day(eomonth(@NEXTMONTHDATE));

                        if @ISFEBEND = 1
                        begin
                            if @DAY <= @MAXDAYOFTARGETMONTH
                                set @POTENTIALDATE = datefromparts(year(@NEXTMONTHDATE), month(@NEXTMONTHDATE), @DAY);
                            else
                                set @POTENTIALDATE = eomonth(@NEXTMONTHDATE);
                        end
                        else
                        begin
                            set @POTENTIALDATE = @NEXTMONTHDATE;
                        end
                    end
                end
          else if @FREQUENCYCODE = 6 --Bimonthly

                        set @POTENTIALDATE = dateadd(month, 2, @POTENTIALDATE);        
                    else if @FREQUENCYCODE = 7 --Semi-monthly

                    begin
                        if datepart(day, @POTENTIALDATE) < 15
                            set @POTENTIALDATE = dateadd(day, (15 - datepart(day, @POTENTIALDATE)), @POTENTIALDATE);
                        else
                        begin
                            set @POTENTIALDATE = dateadd(month, 1, @POTENTIALDATE)
                            set @POTENTIALDATE = dateadd(day, (-1 * datepart(day, @POTENTIALDATE)) + 1, @POTENTIALDATE);
                        end             
                    end
                    else if @FREQUENCYCODE = 8 --Biweekly

                        set @POTENTIALDATE = dateadd(day, 14, @POTENTIALDATE);
                    else if @FREQUENCYCODE = 9 --Weekly

                        set @POTENTIALDATE = dateadd(week, 1, @POTENTIALDATE);
                    else if @FREQUENCYCODE = 10 --Every4Weeks

                        set @POTENTIALDATE = dateadd(day, 28, @POTENTIALDATE);
                    else
                        set @POTENTIALDATE = dateadd(day, 1, @NEXTTRANSACTIONDATE) --Don't know how to handle the frequency. Just use the day after @NEXTTRANSACTIONDATE so it'll break out of the loop


                end

                return @POTENTIALDATE;
            end