USP_MEMBERSHIP_MERGE

Parameters

Parameter Parameter Type Mode Description
@SOURCEMEMBERSHIPID uniqueidentifier IN
@SOURCECONSTITUENTID uniqueidentifier IN
@TARGETCONSTITUENTID uniqueidentifier IN
@EXCLUDEDUPES bit IN
@CHANGEAGENTID uniqueidentifier IN
@CURRENTDATE datetime IN

Definition

Copy


CREATE procedure dbo.USP_MEMBERSHIP_MERGE (
    @SOURCEMEMBERSHIPID uniqueidentifier,
    @SOURCECONSTITUENTID uniqueidentifier,
    @TARGETCONSTITUENTID uniqueidentifier,
    @EXCLUDEDUPES bit = 0,
    @CHANGEAGENTID uniqueidentifier = null,
    @CURRENTDATE datetime = null
)
as
    set nocount on;

    if @CHANGEAGENTID is null  
        exec dbo.USP_CHANGEAGENT_GETORCREATECHANGEAGENT @CHANGEAGENTID output;

    if @CURRENTDATE is null
        set @CURRENTDATE = getdate();

    declare @SOURCEMEMBERID uniqueidentifier;
    declare @SOURCEISPRIMARY bit;

    begin try

        select
            @SOURCEMEMBERID = ID,
            @SOURCEISPRIMARY = ISPRIMARY
        from
            dbo.MEMBER
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID
            and CONSTITUENTID = @SOURCECONSTITUENTID
            and ISDROPPED = 0;

        -- Check if source is on the membership

        if @SOURCEMEMBERID is null
            raiserror('BBERR_SOURCENOTONMEMBERSHIP', 13, 1);

        declare @TARGETMEMBERID uniqueidentifier;
        declare @TARGETISPRIMARY bit;

        -- Check if the target is currently a member of the merging membership

        select
            @TARGETMEMBERID = ID,
            @TARGETISPRIMARY = ISPRIMARY
        from
            dbo.MEMBER
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID
            and CONSTITUENTID = @TARGETCONSTITUENTID
            and ISDROPPED = 0;

        -- Special case if target is also a member of this membership

        if @TARGETMEMBERID is not null
        begin
            -- Move source's cards to constituent

            update dbo.MEMBERSHIPCARD set
                MEMBERID = @TARGETMEMBERID,
                CHANGEDBYID = @CHANGEAGENTID,
                DATECHANGED = @CURRENTDATE
            where
                MEMBERID = @SOURCEMEMBERID;

            -- Delete the duplicate member record

            -- Should we just drop the member here?

            exec dbo.USP_MEMBER_DELETEBYID_WITHCHANGEAGENTID @SOURCEMEMBERID, @CHANGEAGENTID;

            -- Make the target primary if the source used to be

            update dbo.MEMBER set
                ISPRIMARY = 1,
                CHANGEDBYID = @CHANGEAGENTID,
                DATECHANGED = @CURRENTDATE
            where
                ID = @TARGETMEMBERID
                and ISPRIMARY = 0
                and @SOURCEISPRIMARY = 1;

            return 0;
        end

        -- Get the membership's program info

        declare @MEMBERSHIPPROGRAMID uniqueidentifier;
        declare @ALLOWMULTIPLEMEMBERSHIPS bit;
        declare @SOURCEMEMBERSHIPSTATUSCODE tinyint;

        select top 1
            @MEMBERSHIPPROGRAMID = MEMBERSHIP.MEMBERSHIPPROGRAMID,
            @ALLOWMULTIPLEMEMBERSHIPS = MEMBERSHIPPROGRAM.ALLOWMULTIPLEMEMBERSHIPS,
            @SOURCEMEMBERSHIPSTATUSCODE = MEMBERSHIP.STATUSCODE
        from
            dbo.MEMBERSHIP
        inner join
            dbo.MEMBERSHIPPROGRAM on MEMBERSHIPPROGRAM.ID = MEMBERSHIP.MEMBERSHIPPROGRAMID
        where
            MEMBERSHIP.ID = @SOURCEMEMBERSHIPID;

        -- Get target's membership ID with the same program if one exists

        declare @TARGETMEMBERSHIPID uniqueidentifier;
        select
            @TARGETMEMBERSHIPID = MEMBERSHIP.ID,
            @TARGETMEMBERID = MEMBER.ID,
            @TARGETISPRIMARY = MEMBER.ISPRIMARY
        from
            dbo.MEMBER
        inner join
            dbo.MEMBERSHIP on MEMBERSHIP.ID = MEMBER.MEMBERSHIPID
        where
            MEMBERSHIP.MEMBERSHIPPROGRAMID = @MEMBERSHIPPROGRAMID
            and MEMBERSHIP.STATUSCODE <> 1  -- Cancelled

            and MEMBER.CONSTITUENTID = @TARGETCONSTITUENTID
            and MEMBER.ISDROPPED = 0;

        exec dbo.USP_MEMBERSHIP_MERGEEXCEPTIONS @SOURCEMEMBERSHIPID, @SOURCECONSTITUENTID, @MEMBERSHIPPROGRAMID, @TARGETCONSTITUENTID    

        -- Ignore moving or merging memberships of the same program when EXCLUDEDUPES is true

        if @TARGETMEMBERID is not null and @EXCLUDEDUPES = 1 and @SOURCEMEMBERSHIPSTATUSCODE <> 1  -- Cancelled

        begin
            return 0;
        end

        -- If the target does not have a membership with this program or if the program allows multiple memberships or if the membership is cancelled, just move the membership over

        if @ALLOWMULTIPLEMEMBERSHIPS = 1 or @TARGETMEMBERSHIPID is null or @SOURCEMEMBERSHIPSTATUSCODE = 1  -- Cancelled

        begin
            update dbo.MEMBER set
                CONSTITUENTID = @TARGETCONSTITUENTID,
                CHANGEDBYID = @CHANGEAGENTID,
                DATECHANGED = @CURRENTDATE
            where
                ID = @SOURCEMEMBERID;

            return 0;
        end

        -- The target already has a membership with the same program so we need to merge the transactions


        -- This table will contain updates that need to be made to transaction records

        declare @TRANSACTIONUPDATES table (
            ID uniqueidentifier,
            ACTIONCODE tinyint,
            EXPIRATIONDATE datetime
        );

        -- Declare previous and current transaction variables used to determine action changes

        declare @PREVIOUSTRANSACTIONID uniqueidentifier;
        declare @PREVIOUSMEMBERSHIPID uniqueidentifier;
        declare @PREVIOUSACTIONCODE tinyint;
        declare @PREVIOUSTRANSACTIONDATE datetime;
        declare @PREVIOUSEXPIRATIONDATE datetime;
        declare @PREVIOUSMEMBERSHIPLEVELID uniqueidentifier;
        declare @PREVIOUSMEMBERSHIPLEVELTERMID uniqueidentifier;

        declare @CURRENTTRANSACTIONID uniqueidentifier;
        declare @CURRENTMEMBERSHIPID uniqueidentifier;
        declare @CURRENTACTIONCODE tinyint;
        declare @CURRENTTRANSACTIONDATE datetime;
        declare @CURRENTEXPIRATIONDATE datetime;
        declare @CURRENTMEMBERSHIPLEVELID uniqueidentifier;
        declare @CURRENTMEMBERSHIPLEVELTERMID uniqueidentifier;

        -- The join and expiration dates could be different after merging transactions

        declare @NEWJOINDATE datetime;
        declare @LASTRENEWEDON datetime;
        declare @CALCULATEDEXPIRATIONDATE datetime;

        -- Loop through transactions and determine proper actions

        declare TRANSACTION_CURSOR cursor local static for
        select
            MEMBERSHIPTRANSACTION.ID,
            MEMBERSHIPTRANSACTION.MEMBERSHIPID,
            MEMBERSHIPTRANSACTION.ACTIONCODE,
            MEMBERSHIPTRANSACTION.TRANSACTIONDATE,
            MEMBERSHIPTRANSACTION.EXPIRATIONDATE,
            MEMBERSHIPTRANSACTION.MEMBERSHIPLEVELID,
            MEMBERSHIPTRANSACTION.MEMBERSHIPLEVELTERMID
        from
            dbo.MEMBERSHIPTRANSACTION
        inner join
            dbo.MEMBERSHIPLEVEL on MEMBERSHIPLEVEL.ID = MEMBERSHIPTRANSACTION.MEMBERSHIPLEVELID
        where
            MEMBERSHIPTRANSACTION.MEMBERSHIPID in (@SOURCEMEMBERSHIPID, @TARGETMEMBERSHIPID)
        order by
            MEMBERSHIPTRANSACTION.TRANSACTIONDATE,
            MEMBERSHIPTRANSACTION.DATEADDED;

        open TRANSACTION_CURSOR;

        fetch next from TRANSACTION_CURSOR into
            @CURRENTTRANSACTIONID,
            @CURRENTMEMBERSHIPID,
            @CURRENTACTIONCODE,
            @CURRENTTRANSACTIONDATE,
            @CURRENTEXPIRATIONDATE,
            @CURRENTMEMBERSHIPLEVELID,
            @CURRENTMEMBERSHIPLEVELTERMID;

        declare @NUMBEROFTRANSACTIONS int = @@cursor_rows;
        declare @CURRENTTRANSACTIONNUMBER int = 0;

        set @NEWJOINDATE = @CURRENTTRANSACTIONDATE;

        while @@fetch_status = 0
        begin
            set @CURRENTTRANSACTIONNUMBER = @CURRENTTRANSACTIONNUMBER + 1;

            if @PREVIOUSTRANSACTIONID is not null and @CURRENTACTIONCODE <> 4  -- Drop

            begin
                set @CURRENTACTIONCODE = dbo.UFN_MEMBERSHIPTRANSACTION_DETERMINENEWACTIONCODE(@PREVIOUSMEMBERSHIPLEVELID, @PREVIOUSEXPIRATIONDATE, @PREVIOUSACTIONCODE, @CURRENTMEMBERSHIPLEVELID, @CURRENTTRANSACTIONDATE);

                if @CURRENTACTIONCODE in (1,2,3)  -- Renew, Upgrade, Downgrade

                    set @LASTRENEWEDON = @CURRENTTRANSACTIONDATE;

                if @CURRENTTRANSACTIONNUMBER = @NUMBEROFTRANSACTIONS
                    and not (
                        @CURRENTACTIONCODE = 2  -- Upgrade

                        and @CURRENTEXPIRATIONDATE = @PREVIOUSEXPIRATIONDATE
                    )
                begin
                    if @CURRENTACTIONCODE in (0,5)  -- Join, Rejoin

                        set @CALCULATEDEXPIRATIONDATE = dbo.UFN_MEMBERSHIP_CALCULATEEXPIRATIONDATEBYLEVEL(@CURRENTMEMBERSHIPLEVELID, @CURRENTMEMBERSHIPLEVELTERMID, @CURRENTTRANSACTIONDATE);
                    else
                        set @CALCULATEDEXPIRATIONDATE = dbo.UFN_MEMBERSHIP_CALCULATEEXPIRATIONDATEBYLEVEL(@CURRENTMEMBERSHIPLEVELID, @CURRENTMEMBERSHIPLEVELTERMID, @PREVIOUSEXPIRATIONDATE);

                    if @CALCULATEDEXPIRATIONDATE > @CURRENTEXPIRATIONDATE
                        set @CURRENTEXPIRATIONDATE = @CALCULATEDEXPIRATIONDATE;
                end
            end

            insert into @TRANSACTIONUPDATES (
                ID,
                ACTIONCODE,
                EXPIRATIONDATE
            )
            values (
                @CURRENTTRANSACTIONID,
                @CURRENTACTIONCODE,
                @CURRENTEXPIRATIONDATE
            );

            set @PREVIOUSTRANSACTIONID = @CURRENTTRANSACTIONID;
            set @PREVIOUSMEMBERSHIPID = @CURRENTMEMBERSHIPID;
            set @PREVIOUSACTIONCODE = @CURRENTACTIONCODE;
            set @PREVIOUSTRANSACTIONDATE = @CURRENTTRANSACTIONDATE;
            set @PREVIOUSEXPIRATIONDATE = @CURRENTEXPIRATIONDATE;
            set @PREVIOUSMEMBERSHIPLEVELID = @CURRENTMEMBERSHIPLEVELID;
            set @PREVIOUSMEMBERSHIPLEVELTERMID = @CURRENTMEMBERSHIPLEVELTERMID;

            fetch next from TRANSACTION_CURSOR into
                @CURRENTTRANSACTIONID,
                @CURRENTMEMBERSHIPID,
                @CURRENTACTIONCODE,
                @CURRENTTRANSACTIONDATE,
                @CURRENTEXPIRATIONDATE,
                @CURRENTMEMBERSHIPLEVELID,
                @CURRENTMEMBERSHIPLEVELTERMID;
        end

        close TRANSACTION_CURSOR;
        deallocate TRANSACTION_CURSOR;

        -- Update the transactions with the new merged values

        -- Should we update only the transactions on the target,

        -- and insert new transaction records for the transactions merged from the source?

        update dbo.MEMBERSHIPTRANSACTION set
            MEMBERSHIPID = @TARGETMEMBERSHIPID,
            ACTIONCODE = TRANSACTIONUPDATES.ACTIONCODE,
            EXPIRATIONDATE = TRANSACTIONUPDATES.EXPIRATIONDATE,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        from
            dbo.MEMBERSHIPTRANSACTION
        inner join
            @TRANSACTIONUPDATES as TRANSACTIONUPDATES on TRANSACTIONUPDATES.ID = MEMBERSHIPTRANSACTION.ID
        where
            MEMBERSHIPTRANSACTION.MEMBERSHIPID <> @TARGETMEMBERID
            or MEMBERSHIPTRANSACTION.ACTIONCODE <> TRANSACTIONUPDATES.ACTIONCODE
            or MEMBERSHIPTRANSACTION.EXPIRATIONDATE <> TRANSACTIONUPDATES.EXPIRATIONDATE;

        -- Update the membership with merged values

        update dbo.MEMBERSHIP set
            STATUSCODE = NEWMEMBERSHIPSTATUS.STATUSCODE,
            JOINDATE = @NEWJOINDATE,
            LASTRENEWEDON = @LASTRENEWEDON,
            MEMBERSHIPLEVELID = MEMBERSHIPTRANSACTION.MEMBERSHIPLEVELID,
            MEMBERSHIPLEVELTERMID = MEMBERSHIPTRANSACTION.MEMBERSHIPLEVELTERMID,
            MEMBERSHIPLEVELTYPECODEID = MEMBERSHIPTRANSACTION.MEMBERSHIPLEVELTYPECODEID,
            COMMENTS = MEMBERSHIPTRANSACTION.COMMENTS,
            EXPIRATIONDATE = MEMBERSHIPTRANSACTION.EXPIRATIONDATE,
            GIVENBYID = MEMBERSHIPTRANSACTION.DONORID,
            ISGIFT = MEMBERSHIPTRANSACTION.ISGIFT,
            NUMBEROFCHILDREN = LATESTTRANSACTIONMEMBERSHIP.NUMBEROFCHILDREN,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        from
            dbo.MEMBERSHIP
        inner join
            dbo.MEMBERSHIPTRANSACTION on MEMBERSHIPTRANSACTION.MEMBERSHIPID = MEMBERSHIP.ID
        outer apply
            dbo.UFN_MEMBERSHIPTRANSACTION_CALCULATEMEMBERSHIPSTATUSCODE(MEMBERSHIPTRANSACTION.ID, @CURRENTDATE) as NEWMEMBERSHIPSTATUS
        outer apply (
            select NUMBEROFCHILDREN
            from dbo.MEMBERSHIP
            where ID = @PREVIOUSMEMBERSHIPID
        ) as LATESTTRANSACTIONMEMBERSHIP
        where
            MEMBERSHIPTRANSACTION.ID = @PREVIOUSTRANSACTIONID;

        -- Keep only members and cards from the latest transaction

        -- TODO:  Should we be moving cards from one membership to another

        -- since the membership ID can be printed on cards?

        declare @DROPMEMBERSFROMMEMBERSHIPID uniqueidentifier;

        if @PREVIOUSMEMBERSHIPID = @SOURCEMEMBERSHIPID
        begin
            set @DROPMEMBERSFROMMEMBERSHIPID = @TARGETMEMBERSHIPID;

            if @SOURCEISPRIMARY = 1
            begin
                -- Since the source membership was the last updated,

                -- and the source was primary, make sure that the target is primary as well

                if @TARGETISPRIMARY = 0
                begin
                    update dbo.MEMBER set
                        ISPRIMARY = 0,
                        CHANGEDBYID = @CHANGEAGENTID,
                        DATECHANGED = @CURRENTDATE
                    where
                        MEMBERSHIPID = @TARGETMEMBERSHIPID
                        and ISPRIMARY = 1;

                    update dbo.MEMBER set
                        ISPRIMARY = 1,
                        CHANGEDBYID = @CHANGEAGENTID,
                        DATECHANGED = @CURRENTDATE
                    where
                        ID = @TARGETMEMBERID;
                end
            end

            else
            begin
                -- We need to unmark the target as primary since someone other

                -- than the source is marked as primary and will be merging over

                if @TARGETISPRIMARY = 1
                begin
                    update dbo.MEMBER set
                        ISPRIMARY = 0,
                        CHANGEDBYID = @CHANGEAGENTID,
                        DATECHANGED = @CURRENTDATE
                    where
                        ID = @TARGETMEMBERID;
                end
            end
        end

        else
        begin
            set @DROPMEMBERSFROMMEMBERSHIPID = @SOURCEMEMBERSHIPID;
        end

        update dbo.MEMBER set
            ISDROPPED = 1,
            ISPRIMARY = 0,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPID = @DROPMEMBERSFROMMEMBERSHIPID
            and ID <> @TARGETMEMBERID  -- Make sure we don't drop the Target

            and ISDROPPED = 0;

        update dbo.MEMBERSHIPCARD set
            STATUSCODE = 2,  -- Cancelled

            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        from
            dbo.MEMBERSHIPCARD
        inner join
            dbo.MEMBER on MEMBER.ID = MEMBERSHIPCARD.MEMBERID
        where
            MEMBER.MEMBERSHIPID = @DROPMEMBERSFROMMEMBERSHIPID
            and STATUSCODE <> 2;  -- Cancelled


        -- Moving over all Add-ons regardless if they allow multiple or not.

        -- Add-ons should be moved before members to avoid the valid number of members constraint.

        -- These are linked to revenue and should not be deleted.

        update dbo.MEMBERSHIPADDON set
            MEMBERSHIPID = @TARGETMEMBERSHIPID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID;

        -- Move the membership cards over from the source member since that member isn't moved over

        update dbo.MEMBERSHIPCARD set
            MEMBERID = @TARGETMEMBERID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERID = @SOURCEMEMBERID;

        update dbo.MEMBER set
            MEMBERSHIPID = @TARGETMEMBERSHIPID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID
            and ID <> @SOURCEMEMBERID;

        update dbo.SALESORDERITEMMEMBERSHIPADDON set
            MEMBERSHIPID = @TARGETMEMBERSHIPID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID;

        -- Update the expiration dates of Add-ons linked to the final transaction

        update dbo.MEMBERSHIPADDON set
            EXPIRATIONDATE = @PREVIOUSEXPIRATIONDATE,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPTRANSACTIONID = @PREVIOUSTRANSACTIONID
            and EXPIRATIONDATE <> @PREVIOUSEXPIRATIONDATE;

        -- Update EXISTINGMEMBERSHIPID on membership dues batches so they won't be deleted

        -- when the source membership is deleted

        update dbo.BATCHMEMBERSHIPDUES set
            EXISTINGMEMBERSHIPID = @TARGETMEMBERSHIPID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            EXISTINGMEMBERSHIPID = @SOURCEMEMBERSHIPID;

        -- Make sure the sales order item membership is updated to the target membership.

        update dbo.SALESORDERITEMMEMBERSHIP
            set MEMBERSHIPID = @TARGETMEMBERSHIPID,
                CHANGEDBYID = @CHANGEAGENTID,
                DATECHANGED = @CURRENTDATE
        where 
            MEMBERSHIPID = @SOURCEMEMBERSHIPID;

        -- Make sure MEMBERID fields are updated to the target member ID

        update dbo.SALESORDERITEMMEMBER
            set MEMBERID = @TARGETMEMBERID,
                CHANGEDBYID = @CHANGEAGENTID,
                DATECHANGED = @CURRENTDATE
        where 
            MEMBERID = @SOURCEMEMBERID;

        -- Move over notes from the source membership to the target membership

        update dbo.MEMBERNOTE set
            MEMBERSHIPID = @TARGETMEMBERSHIPID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID;

        -- Move over media links from the source membership to the target membership

        update dbo.MEMBERMEDIALINK set
            MEMBERSHIPID = @TARGETMEMBERSHIPID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID;

        -- Move over attachments from the source membership to the target membership

        update dbo.MEMBERATTACHMENT set
            MEMBERSHIPID = @TARGETMEMBERSHIPID,
            CHANGEDBYID = @CHANGEAGENTID,
            DATECHANGED = @CURRENTDATE
        where
            MEMBERSHIPID = @SOURCEMEMBERSHIPID;

        -- Delete the source membership

        exec dbo.USP_MEMBERSHIP_DELETEBYID_WITHCHANGEAGENTID @SOURCEMEMBERSHIPID, @CHANGEAGENTID;
    end try

    begin catch
        exec dbo.USP_RAISE_ERROR;
        return 1;
    end catch

    return 0;