USP_MERGE_GROUPMEMBERSHIP
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@SOURCEID | uniqueidentifier | IN | |
@TARGETID | uniqueidentifier | IN | |
@CHANGEAGENTID | uniqueidentifier | IN | |
@DATECHANGED | datetime | IN |
Definition
Copy
CREATE procedure dbo.USP_MERGE_GROUPMEMBERSHIP
(
@SOURCEID uniqueidentifier,
@TARGETID uniqueidentifier,
@CHANGEAGENTID uniqueidentifier,
@DATECHANGED datetime
)
as
set nocount on;
--This code is similar to what USP_CONSTITUENCY_MERGE builds but the table does not follow the same structure
--so I've broken it out here.
--Source has no group memberships
if not exists(select top 1 1 from dbo.GROUPMEMBER where MEMBERID = @SOURCEID)
return 0;
declare @CURRENTDATE datetime = getdate();
declare @TARGETCURRENTHOUSEHOLD uniqueidentifier = null;
select
@TARGETCURRENTHOUSEHOLD = GROUPMEMBER.GROUPID
from
dbo.GROUPMEMBER
inner join
dbo.GROUPDATA on GROUPDATA.ID = GROUPMEMBER.GROUPID
where
GROUPMEMBER.MEMBERID = @TARGETID and
dbo.UFN_GROUPMEMBER_ISCURRENTMEMBER(GROUPMEMBER.ID) = 1;
--Find all the overlapping group memberships and if the source was the primary record
declare @OVERLAP_GROUPS table(ID uniqueidentifier, SOURCEISPRIMARY bit);
insert into @OVERLAP_GROUPS
select
GMS.GROUPID,
max(convert(int, GMS.ISPRIMARY))
from
dbo.GROUPMEMBER GMS
inner join
dbo.GROUPMEMBER GMT on GMT.GROUPID = GMS.GROUPID
where
GMS.MEMBERID = @SOURCEID and
GMT.MEMBERID = @TARGETID
group by
GMS.GROUPID;
--Move over all the source group memberships that are not overlapping (don't move source current household if the target is currently in a household)
update
GM
set
MEMBERID = @TARGETID,
CHANGEDBYID = @CHANGEAGENTID, DATECHANGED = @CURRENTDATE
from
dbo.GROUPMEMBER GM
inner join
dbo.GROUPDATA on GROUPDATA.ID = GM.GROUPID
left join
dbo.GROUPMEMBERDATERANGE GMDR on GMDR.GROUPMEMBERID = GM.ID
where
GM.MEMBERID = @SOURCEID and
GM.GROUPID <> @TARGETID and --Make sure source group is not a member of target
not exists (select 1 from @OVERLAP_GROUPS OG where GM.GROUPID = OG.ID) and
(GROUPDATA.GROUPTYPECODE <> 0 or (@TARGETCURRENTHOUSEHOLD is null or GMDR.DATETO is not null));
-- If a household was merged to the target constituent, the household
-- name will need to be updated to reflect the new constituent.
exec dbo.USP_HOUSEHOLD_REFRESHNAME @TARGETID, @CHANGEAGENTID
--Grab all the dates for the given overlapping groups and remove any dates that are disjoint
declare @DATES table(GROUPID uniqueidentifier, DATEFROM datetime, DATETO datetime);
insert into @DATES
select
GROUPID,
DATEFROM,
DATETO
from
@OVERLAP_GROUPS OLG
inner join
dbo.GROUPMEMBER on GROUPMEMBER.GROUPID = OLG.ID
left join
dbo.GROUPMEMBERDATERANGE GMDR on GMDR.GROUPMEMBERID = GROUPMEMBER.ID
where
GROUPMEMBER.MEMBERID in (@SOURCEID, @TARGETID);
delete D1 from
@DATES D1
inner join
@DATES D2 on D2.GROUPID = D1.GROUPID and coalesce(D1.DATETO, '9999-12-31') < coalesce(dateadd(day, -1, D2.DATEFROM), '1753-01-01');
--Find the latest end date (include null) and the earliest start date (exclude null if possible) for each overlapping group
declare @GROUPDATES table(GROUPID uniqueidentifier, DATEFROM datetime, DATETO datetime);
insert into @GROUPDATES
select
GROUPID,
case
when exists(select 1 from @DATES where DATEFROM is null)
then null
else
min(DATEFROM)
end as DATEFROM,
case
when exists(select 1 from @DATES where DATETO is null)
then null
else
max(DATETO)
end as DATETO
from
@DATES
group by
GROUPID;
update
GMDR
set
DATEFROM = SUBQ.DATEFROM,
DATETO = SUBQ.DATETO,
CHANGEDBYID = @CHANGEAGENTID,
DATECHANGED = @DATECHANGED
from
dbo.GROUPMEMBERDATERANGE GMDR
inner join
dbo.GROUPMEMBER on GROUPMEMBER.ID = GMDR.GROUPMEMBERID
inner join
@GROUPDATES SUBQ on SUBQ.GROUPID = GROUPMEMBER.GROUPID
where
GROUPMEMBER.MEMBERID = @TARGETID;
insert into dbo.GROUPMEMBERDATERANGE(GROUPMEMBERID, DATEFROM, DATETO, ADDEDBYID, CHANGEDBYID, DATEADDED, DATECHANGED)
select
GROUPMEMBER.ID,
DATEFROM = SUBQ.DATEFROM,
DATETO = SUBQ.DATETO,
@CHANGEAGENTID, @CHANGEAGENTID, @DATECHANGED, @DATECHANGED
from
dbo.GROUPMEMBER
inner join
@GROUPDATES SUBQ on SUBQ.GROUPID = GROUPMEMBER.GROUPID
where
GROUPMEMBER.MEMBERID = @TARGETID and
not exists(select 1 from dbo.GROUPMEMBERDATERANGE GMDR where GMDR.GROUPMEMBERID = GROUPMEMBER.ID);
--Update the group member roles
--@MERGE_RECORDSET will hold the end result of our operations
--We will use this table to do the final updates back to the record table
declare @MERGE_RECORDSET table
(
ID uniqueidentifier,
GROUPID uniqueidentifier,
GROUPMEMBERROLECODEID uniqueidentifier,
STARTDATE datetime,
ENDDATE datetime
);
declare @ID uniqueidentifier;
declare @GROUPID uniqueidentifier;
declare @GROUPMEMBERROLECODEID uniqueidentifier;
declare @STARTDATE datetime;
declare @ENDDATE datetime;
declare RECORD_CURSOR cursor for
select
GROUPMEMBERROLE.ID,
GROUPMEMBER.GROUPID,
GROUPMEMBERROLE.GROUPMEMBERROLECODEID,
GROUPMEMBERROLE.STARTDATE,
GROUPMEMBERROLE.ENDDATE
from
dbo.GROUPMEMBERROLE
inner join
dbo.GROUPMEMBER on GROUPMEMBER.ID = GROUPMEMBERROLE.GROUPMEMBERID
inner join
@OVERLAP_GROUPS OLG on OLG.ID = GROUPMEMBER.GROUPID
where
GROUPMEMBER.MEMBERID in (@SOURCEID, @TARGETID)
order by
GROUPMEMBERROLECODEID,
STARTDATE,
ENDDATE
open RECORD_CURSOR;
fetch next from RECORD_CURSOR
into @ID, @GROUPID, @GROUPMEMBERROLECODEID, @STARTDATE, @ENDDATE;
while @@FETCH_STATUS = 0
begin
declare @OVERLAPPINGID uniqueidentifier = null;
select
@OVERLAPPINGID = ID
from
@MERGE_RECORDSET MRS
where
MRS.GROUPID = @GROUPID and
MRS.GROUPMEMBERROLECODEID = @GROUPMEMBERROLECODEID and
(
coalesce(MRS.STARTDATE, '1753-01-01') between coalesce(@STARTDATE, '1753-01-01') and coalesce(@ENDDATE, '9999-12-31') or
coalesce(MRS.ENDDATE, '9999-12-31') between coalesce(@STARTDATE, '1753-01-01') and coalesce(@ENDDATE, '9999-12-31') or
coalesce(@STARTDATE, '1753-01-01') between coalesce(MRS.STARTDATE, '1753-01-01') and coalesce(MRS.ENDDATE, '9999-12-31') or
coalesce(@ENDDATE, '9999-12-31') between coalesce(MRS.STARTDATE, '1753-01-01') and coalesce(MRS.ENDDATE, '9999-12-31')
)
if @OVERLAPPINGID is not null
begin
update MRS set
--Preserve data (i.e. specified date over null)
STARTDATE =
case
when MRS.STARTDATE is null
then @STARTDATE
when @STARTDATE is null
then MRS.STARTDATE
when MRS.STARTDATE < @STARTDATE
then MRS.STARTDATE
else
@STARTDATE
end,
--Preserve status (i.e. currently a member over specified date)
ENDDATE =
case
when MRS.ENDDATE is null or @ENDDATE is null
then null
when MRS.ENDDATE > @ENDDATE
then MRS.ENDDATE
else
@ENDDATE
end
from
@MERGE_RECORDSET MRS
where
MRS.ID = @OVERLAPPINGID;
end
else
begin
insert into @MERGE_RECORDSET
(ID, GROUPID, GROUPMEMBERROLECODEID, STARTDATE, ENDDATE)
values
(@ID, @GROUPID, @GROUPMEMBERROLECODEID, @STARTDATE, @ENDDATE)
end
fetch next from RECORD_CURSOR
into @ID, @GROUPID, @GROUPMEMBERROLECODEID, @STARTDATE, @ENDDATE;
end
close RECORD_CURSOR;
deallocate RECORD_CURSOR;
declare @CONTEXTCACHE varbinary(128);
set @CONTEXTCACHE = context_info();
if not @CHANGEAGENTID is null
set context_info @CHANGEAGENTID;
if not @CONTEXTCACHE is null
set context_info @CONTEXTCACHE;
--Update the records in our final set with the new dates and to point to the target
delete GROUPMEMBERROLE from
dbo.GROUPMEMBERROLE
inner join
dbo.GROUPMEMBER on GROUPMEMBER.ID = GROUPMEMBERROLE.GROUPMEMBERID
inner join
@OVERLAP_GROUPS OLG on OLG.ID = GROUPMEMBER.GROUPID
where
GROUPMEMBER.MEMBERID = @TARGETID and
not exists(select ID from @MERGE_RECORDSET where ID = GROUPMEMBERROLE.ID);
--Update the records in our final set with the new dates and to point to the target
update
GROUPMEMBERROLE
set
GROUPMEMBERID = GMT.ID,
STARTDATE = MRS.STARTDATE,
ENDDATE = MRS.ENDDATE,
CHANGEDBYID = @CHANGEAGENTID, DATECHANGED = @CURRENTDATE
from
dbo.GROUPMEMBERROLE
inner join
@MERGE_RECORDSET MRS on MRS.ID = GROUPMEMBERROLE.ID
inner join
dbo.GROUPMEMBER GMT on GMT.MEMBERID = @TARGETID and GMT.GROUPID = MRS.GROUPID;
--End update group member roles
exec dbo.USP_CONSTITUENTMERGE_UPDATEGROUPADDRESSMAILPREFS @TARGETID, @SOURCEID, @CHANGEAGENTID, 0
exec dbo.USP_CONSTITUENTMERGE_UPDATEGROUPEMAILMAILPREFS @TARGETID, @SOURCEID, @CHANGEAGENTID, 0
--Get rid of the source member records
declare @GROUPMEMBERIDS table (ID uniqueidentifier)
insert into @GROUPMEMBERIDS(ID)
select GM.ID from dbo.GROUPMEMBER as GM where GM.MEMBERID = @SOURCEID
delete from dbo.GROUPMEMBERROLE where GROUPMEMBERID in (select ID from @GROUPMEMBERIDS)
delete from dbo.GROUPMEMBERDATERANGE where GROUPMEMBERID in (select ID from @GROUPMEMBERIDS)
delete from dbo.GROUPMEMBER where MEMBERID = @SOURCEID
--Associate the old source primary group memberships that were overlapping to the target
update
GM
set
ISPRIMARY = 1,
CHANGEDBYID = @CHANGEAGENTID,
DATECHANGED = @DATECHANGED
from
dbo.GROUPMEMBER GM
left join
dbo.GROUPMEMBERDATERANGE GMDR on GMDR.GROUPMEMBERID = GM.ID
where
MEMBERID = @TARGETID and
exists(select 1 from @OVERLAP_GROUPS OLG where OLG.ID = GROUPID and OLG.SOURCEISPRIMARY = 1) and
not exists(select 1 from @GROUPDATES GD where GD.GROUPID = GROUPID and (coalesce(GMDR.DATEFROM, '1753-01-01') = coalesce(GD.DATEFROM, '1753-01-01')
and coalesce(GMDR.DATETO, '9999-12-31') = coalesce(GD.DATETO, '9999-12-31')));
return 0;