USP_DATALIST_MEMBERSHIPCONVERSIONREPORT

Fetches Membership Renewal information

Parameters

Parameter Parameter Type Mode Description
@STARTDATE datetime IN Start Date
@ENDDATE datetime IN End Date
@MEMBERSHIPPROGRAMID uniqueidentifier IN Membership Program
@GROUPBYTIER bit IN Group by tier
@HIDECOLUMNSROWSWITHNODATA bit IN Hide columns and rows with no data

Definition

Copy


CREATE procedure dbo.USP_DATALIST_MEMBERSHIPCONVERSIONREPORT
(
    @STARTDATE datetime = null,
    @ENDDATE datetime = null,
    @MEMBERSHIPPROGRAMID uniqueidentifier = null,
    @GROUPBYTIER bit = 0,
    @HIDECOLUMNSROWSWITHNODATA bit = 0
)
as
    set nocount on;

if (@STARTDATE is null) or (@ENDDATE is null) begin
    raiserror('Invalid date range.', 13, 1);
    return 1;
end

-- Prevent lapsing people in the future

if @ENDDATE > getdate() set @ENDDATE = getdate();

-- Make sure we have the largest window for the given dates

set @STARTDATE = dbo.UFN_DATE_GETEARLIESTTIME(@STARTDATE);
set @ENDDATE = dbo.UFN_DATE_GETLATESTTIME(@ENDDATE);


declare @TRANSACTIONS as table (
    MEMBERSHIPID uniqueidentifier,
    BEGINNINGLEVELID uniqueidentifier,
    BEGINNINGISACTIVE bit,
    ENDINGLEVELID uniqueidentifier,
    ENDINGACTIONCODE tinyint,
    ISDECEASED bit
);

-- Get memberships as of start date and memberships as of end date, then group them according to the net change.

-- - BEGINNING is the most recent transaction *before the interval*, regardless of how recent or what kind of transaction.

-- - ENDING is the latest transaction that occurred *during the interval* for each membership.

-- - ENDING has one additional limitation: either its expiration date must be after the end of the interval or its action must be 'drop'.

-- - - This removes transactions that lapse before the interval ends but keeps explicit 'drop' transactions for previously lapsed memberships (ultimate result should still be 'Not renewed' for both).

with BEGINNING as
(
    select MT.MEMBERSHIPID,
        MT.MEMBERSHIPLEVELID,
        MT.EXPIRATIONDATE,
        TRANSACTIONEXPIRATIONDATES.NOLONGERACTIVEDATE,
        MT.ACTIONCODE
    from dbo.UFN_MEMBERSHIP_LATESTTRANSACTIONASOF_BULK(dbo.UFN_DATE_GETLATESTTIME(@STARTDATE - 1)) MT
    inner join dbo.UFN_MEMBERSHIP_WITHRENEWALWINDOW_GETNOLONGERACTIVEDATES() as TRANSACTIONEXPIRATIONDATES
        on MT.ID = TRANSACTIONEXPIRATIONDATES.MEMBERSHIPTRANSACTIONID
    inner join dbo.MEMBERSHIPLEVEL on MT.MEMBERSHIPLEVELID = MEMBERSHIPLEVEL.ID
    where MEMBERSHIPLEVEL.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID
),
ENDING as
(
    select MEMBERSHIPID,
        MEMBERSHIPLEVELID,
        ACTIONCODE
    from dbo.UFN_MEMBERSHIP_LATESTTRANSACTIONASOF_BULK(@ENDDATE) MT
    inner join dbo.MEMBERSHIPLEVEL on MT.MEMBERSHIPLEVELID = MEMBERSHIPLEVEL.ID
    where MEMBERSHIPLEVEL.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID
        and TRANSACTIONDATE >= @STARTDATE
        and (EXPIRATIONDATE > @ENDDATE or EXPIRATIONDATE is null or ACTIONCODE = 4)
)
insert into @TRANSACTIONS
select
    coalesce(BEGINNING.MEMBERSHIPID, ENDING.MEMBERSHIPID),
    BEGINNING.MEMBERSHIPLEVELID,
    case
        when (BEGINNING.MEMBERSHIPID is null or BEGINNING.NOLONGERACTIVEDATE < @STARTDATE or BEGINNING.ACTIONCODE = 4) then 0
        else 1
    end as BEGINNINGISACTIVE,
    ENDING.MEMBERSHIPLEVELID,
    ENDING.ACTIONCODE,
    0 -- ISDECEASED is set below

from BEGINNING full join ENDING
    on BEGINNING.MEMBERSHIPID = ENDING.MEMBERSHIPID
where BEGINNING.EXPIRATIONDATE between @STARTDATE and @ENDDATE
    or ENDING.MEMBERSHIPID is not null        --Limit output to only the memberships that have changed during the time period (either a lapse or a new transaction has occurred)


-- Get all memberships with no living members and set 'deceased' accordingly

-- I'm not sure this implementation is correct, because it does not take date of death into account.

update @TRANSACTIONS
set ISDECEASED = 1
where
    MEMBERSHIPID not in (
        select MEMBER.MEMBERSHIPID
        from dbo.MEMBER
            inner join dbo.MEMBERSHIP on MEMBER.MEMBERSHIPID = MEMBERSHIP.ID
            left join dbo.DECEASEDCONSTITUENT on DECEASEDCONSTITUENT.ID = MEMBER.CONSTITUENTID
        where MEMBERSHIP.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID
            and DECEASEDCONSTITUENT.ID is null
    )

declare @RETURNTABLE table(
    STARTLEVELNAME nvarchar(255),
    STARTLEVELRANK int,
    ENDLEVELNAME nvarchar(255),
    ENDLEVELRANK int,
    MOVEMENTCOUNT bigint,
    STARTLEVELACTIVE int
)

insert into @RETURNTABLE
select
    case @GROUPBYTIER
        when 0 then MLSTART.NAME
        when 1 then coalesce(TIERSTART.DESCRIPTION, '(no reporting group)')
    end as STARTLEVELNAME,
    case @GROUPBYTIER
        when 0 then (MLSTART.SEQUENCE + 2)
        when 1 then coalesce((TIERSTART.SEQUENCE + 3), 2)
    end as STARTLEVELRANK,
    case @GROUPBYTIER
        when 0 then MLEND.NAME
        when 1 then coalesce(TIEREND.DESCRIPTION, '(no reporting group)')
    end as ENDLEVELNAME,
    case @GROUPBYTIER
        when 0 then (MLEND.SEQUENCE + 2)
        when 1 then coalesce((TIEREND.SEQUENCE + 3), 2)
    end as ENDLEVELRANK,
    (
        select count(MEMBERSHIPID)
        from @TRANSACTIONS
        where BEGINNINGLEVELID = MLSTART.ID
            and BEGINNINGISACTIVE = 1        -- Don't include any that were dropped before or during the interval; those go under Rejoin or Not Renewed.

            and ENDINGLEVELID = MLEND.ID
            and ENDINGACTIONCODE <> 4
    ) as MOVEMENTCOUNT,
    0 as STARTLEVELACTIVE
from
    dbo.MEMBERSHIPLEVEL as MLSTART
    inner join dbo.MEMBERSHIPLEVEL as MLEND on MLSTART.MEMBERSHIPPROGRAMID = MLEND.MEMBERSHIPPROGRAMID
    left join dbo.TIERCODE TIERSTART on MLSTART.TIERCODEID = TIERSTART.ID
    left join dbo.TIERCODE TIEREND on MLEND.TIERCODEID = TIEREND.ID
where
    MLSTART.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID
    and MLEND.ISACTIVE = 1

union all

-- Not renewed memberships (lapsed and cancelled, including cancellations that had previously lapsed)

select
    case @GROUPBYTIER
        when 0 then MLSTART.NAME
        when 1 then coalesce(TIERSTART.DESCRIPTION, '(no reporting group)')
    end as STARTLEVELNAME,
    case @GROUPBYTIER
        when 0 then (MLSTART.SEQUENCE + 2)
        when 1 then coalesce((TIERSTART.SEQUENCE + 3), 2)
    end as STARTLEVELRANK,
    'Not renewed' as ENDLEVELNAME,
    0 as ENDLEVELRANK,
    (
        select count(MEMBERSHIPID)
        from @TRANSACTIONS T
        where BEGINNINGLEVELID = MLSTART.ID
            and ((BEGINNINGISACTIVE = 1 and ENDINGLEVELID is null)
                or ENDINGACTIONCODE = 4)
            and ISDECEASED = 0
    ) as MOVEMENTCOUNT,
    MLSTART.ISACTIVE as STARTLEVELACTIVE --throw a flag if the level is active

from
    dbo.MEMBERSHIPLEVEL as MLSTART
    left join dbo.TIERCODE TIERSTART on MLSTART.TIERCODEID = TIERSTART.ID
where
    MLSTART.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID

union all

-- Deceased memberships (those that would have been 'Not renewed' if they hadn't died instead)

select
    case @GROUPBYTIER
        when 0 then MLSTART.NAME
        when 1 then coalesce(TIERSTART.DESCRIPTION, '(no reporting group)')
    end as STARTLEVELNAME,
    case @GROUPBYTIER
        when 0 then (MLSTART.SEQUENCE + 2)
        when 1 then coalesce((TIERSTART.SEQUENCE + 3), 2)
    end as STARTLEVELRANK,
    'Deceased' as ENDLEVELNAME,
    1 as ENDLEVELRANK,
    (
        select count(MEMBERSHIPID)
        from @TRANSACTIONS TNS
        where BEGINNINGLEVELID = MLSTART.ID
            and ((BEGINNINGISACTIVE = 1 and ENDINGLEVELID is null)
                or ENDINGACTIONCODE = 4)
            and ISDECEASED = 1
    ) as MOVEMENTCOUNT,
    0 as STARTLEVELACTIVE
from
    dbo.MEMBERSHIPLEVEL as MLSTART
    left join dbo.TIERCODE TIERSTART on MLSTART.TIERCODEID = TIERSTART.ID
where
    MLSTART.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID

union all

select
    'New' as STARTLEVELNAME,
    0 as STARTLEVELRANK,
    case @GROUPBYTIER
        when 0 then MLEND.NAME
        when 1 then coalesce(TIEREND.DESCRIPTION, '(no reporting group)')
    end as ENDLEVELNAME,
    case @GROUPBYTIER
        when 0 then (MLEND.SEQUENCE + 2)
        when 1 then coalesce((TIEREND.SEQUENCE + 3), 2)
    end as ENDLEVELRANK,
    (
        select count(MEMBERSHIPID)
        from @TRANSACTIONS
        where BEGINNINGLEVELID is null
            and ENDINGLEVELID = MLEND.ID
            and ENDINGACTIONCODE <> 4
    ) as MOVEMENTCOUNT,
    1 as STARTLEVELACTIVE
from
    dbo.MEMBERSHIPLEVEL as MLEND
    left join dbo.TIERCODE TIEREND on MLEND.TIERCODEID = TIEREND.ID
where
    MLEND.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID and
    MLEND.ISACTIVE = 1

union all

-- Rejoins (includes rejoin transactions whose level differs from the previous transaction's level)

select
    'Rejoin' as STARTLEVELNAME,
    1 as STARTLEVELRANK,
    case @GROUPBYTIER
        when 0 then MLEND.NAME
        when 1 then coalesce(TIEREND.DESCRIPTION, '(no reporting group)')
    end as ENDLEVELNAME,
    case @GROUPBYTIER
        when 0 then (MLEND.SEQUENCE + 2)
        when 1 then coalesce((TIEREND.SEQUENCE + 3), 2)
    end as ENDLEVELRANK,
    (
        select count(MEMBERSHIPID)
        from @TRANSACTIONS
        where BEGINNINGLEVELID is not null
            and BEGINNINGISACTIVE = 0
            and ENDINGLEVELID = MLEND.ID
            and ENDINGACTIONCODE <> 4
    ) as MOVEMENTCOUNT,
    1 as STARTLEVELACTIVE
from
    dbo.MEMBERSHIPLEVEL as MLEND
    left join dbo.TIERCODE TIEREND on MLEND.TIERCODEID = TIEREND.ID
where
    MLEND.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID
    and MLEND.ISACTIVE = 1

union all

select
    'New' as STARTLEVELNAME,
    0 as STARTLEVELRANK,
    'Not renewed' as ENDLEVELNAME,
    0 as ENDLEVELRANK,
    0 as MOVEMENTCOUNT,
    1 as STARTLEVELACTIVE

union all

select
    'New' as STARTLEVELNAME,
    0 as STARTLEVELRANK,
    'Deceased' as ENDLEVELNAME,
    1 as ENDLEVELRANK,
    0 as MOVEMENTCOUNT,
    0 as STARTLEVELACTIVE

union all

select
    'Rejoin' as STARTLEVELNAME,
    1 as STARTLEVELRANK,
    'Not renewed' as ENDLEVELNAME,
    0 as ENDLEVELRANK,
    0 as MOVEMENTCOUNT,
    1 as STARTLEVELACTIVE

union all

select
    'Rejoin' as STARTLEVELNAME,
    1 as STARTLEVELRANK,
    'Deceased' as ENDLEVELNAME,
    1 as ENDLEVELRANK,
    0 as MOVEMENTCOUNT,
    0 as STARTLEVELACTIVE

order by
    STARTLEVELRANK,
    ENDLEVELRANK

if @HIDECOLUMNSROWSWITHNODATA = 1
begin

    -- Hide the columns that don't have any value

    delete @RETURNTABLE 
    from @RETURNTABLE RETURNTABLE 
    inner join (
        select ENDLEVELRANK from @RETURNTABLE 
        group by ENDLEVELRANK
        having SUM(MOVEMENTCOUNT) = 0 and ENDLEVELRANK > 1) as GROUPTABLE 
    on RETURNTABLE.ENDLEVELRANK = GROUPTABLE.ENDLEVELRANK 

    -- Hide the rows that don't have any value

    delete @RETURNTABLE 
    from @RETURNTABLE RETURNTABLE 
    inner join (
        select STARTLEVELRANK from @RETURNTABLE 
        group by STARTLEVELRANK
        having SUM(MOVEMENTCOUNT) = 0 and STARTLEVELRANK > 1) as GROUPTABLE 
    on RETURNTABLE.STARTLEVELRANK = GROUPTABLE.STARTLEVELRANK 
end

select STARTLEVELNAME,
    STARTLEVELRANK,
    ENDLEVELNAME,
    ENDLEVELRANK,
    MOVEMENTCOUNT,
    STARTLEVELACTIVE
from @RETURNTABLE 
order by
    STARTLEVELRANK,
    ENDLEVELRANK

return 0;