USP_RELATIONSHIPS_CREATEPARENTORGRELATIONSHIP
This spec is for creating parent of parent relationships between a single subsidiary(ORGID)
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@NONPARENTORGID | uniqueidentifier | IN | |
@PARENTORGID | uniqueidentifier | IN | |
@STARTDATE | date | IN | |
@CHANGEAGENTID | uniqueidentifier | IN | |
@CHANGEDATE | datetime | IN | |
@ADDINITIALRELATIONSHIP | bit | IN | |
@OLDPARENTORGID | uniqueidentifier | IN | |
@RELATIONSHIPENDDATE | date | IN |
Definition
Copy
CREATE procedure dbo.USP_RELATIONSHIPS_CREATEPARENTORGRELATIONSHIP
(
@NONPARENTORGID uniqueidentifier,
@PARENTORGID uniqueidentifier,
@STARTDATE date,
@CHANGEAGENTID uniqueidentifier,
@CHANGEDATE datetime,
@ADDINITIALRELATIONSHIP bit,
@OLDPARENTORGID uniqueidentifier,
@RELATIONSHIPENDDATE date = null
)
as
set nocount on;
if @CHANGEAGENTID is null
exec dbo.USP_CHANGEAGENT_GETORCREATECHANGEAGENT @CHANGEAGENTID output;
if @CHANGEDATE is null
set @CHANGEDATE = getdate();
if @ADDINITIALRELATIONSHIP is null
set @ADDINITIALRELATIONSHIP = 0
if @RELATIONSHIPENDDATE is null
set @RELATIONSHIPENDDATE = getdate();
declare @PARENTOFPARENTCHECK bit;
declare @TOPPARENTCHECK bit;
declare @PARENTOFPARENTORGID uniqueidentifier
declare @PARENTOFPARENTSUBSIDIARYORGID uniqueidentifier
declare @TOPPARENTORGID uniqueidentifier
declare @TOPSUBSIDIARYORGID uniqueidentifier
declare @PARENTORGCODEID uniqueidentifier
declare @SUBSIDIARYORGCODEID uniqueidentifier
declare @SETENDDATE bit
select @PARENTOFPARENTORGID=PARENTOFPARENTORGID,
@PARENTOFPARENTSUBSIDIARYORGID=PARENTOFPARENTSUBSIDIARYORGID,
@TOPPARENTORGID = TOPPARENTORGID,
@TOPSUBSIDIARYORGID = TOPSUBSIDIARYORGID,
@PARENTOFPARENTCHECK=CREATEPARENTOFPARENTRELATIONSHIP,
@TOPPARENTCHECK = CREATETOPPARENTRELATIONSHIP,
@PARENTORGCODEID = PARENTORGID,
@SUBSIDIARYORGCODEID = SUBSIDIARYORGID,
@SETENDDATE = SETENDDATE
from dbo.RELATIONSHIPCONFIGURATIONCORPORATE
--If there is no row in the RELATIONSHIPCONFIGURATIONCORPORATE table then create the default relationship types.
if @PARENTORGCODEID is null
begin
declare @PARENTTYPEID uniqueidentifier = (select ID from dbo.RELATIONSHIPTYPECODE where DESCRIPTION = 'Parent Corporation')
declare @SUBSIDIARYTYPEID uniqueidentifier = (select ID from dbo.RELATIONSHIPTYPECODE where DESCRIPTION = 'Subsidiary')
if @PARENTTYPEID is null
begin
set @PARENTTYPEID = newid()
exec USP_DATAFORMTEMPLATE_ADD_RELATIONSHIPCONFIGURATION @PARENTTYPEID,@CHANGEAGENTID,'Parent Corporation',0,1,1,1,1,1,1,1,1,0,0
end
if @SUBSIDIARYTYPEID is null
begin
set @SUBSIDIARYTYPEID = newid()
exec USP_DATAFORMTEMPLATE_ADD_RELATIONSHIPCONFIGURATION @SUBSIDIARYTYPEID,@CHANGEAGENTID,'Subsidiary',0,1,1,1,1,1,1,1,1,0,0
end
insert into dbo.RELATIONSHIPCONFIGURATIONCORPORATE (ID,PARENTORGID,SUBSIDIARYORGID,CREATEPARENTOFPARENTRELATIONSHIP,CREATETOPPARENTRELATIONSHIP,ADDEDBYID,CHANGEDBYID,DATEADDED,DATECHANGED)
values (newid(),@PARENTTYPEID,@SUBSIDIARYTYPEID,0,0,@CHANGEAGENTID,@CHANGEAGENTID,getDate(),getDate());
set @PARENTORGCODEID = @PARENTTYPEID
set @SUBSIDIARYORGCODEID = @SUBSIDIARYTYPEID
end
--Bug 401235. Prevent corporate structures that include cycles. Allowing cycles the corporate structure
--leads to infinite recursion in the CTEs used later in this stored procedure and it doesn't make any
--business sense to allow them. This check is needed in the case where @NONPARENTORGID and the
--new parent were in the same parent corporation tree before this edit was started and the edit
--is just rearranging the hierarchy. To check for this, we allow the first repeated row into the
--RECURSIVEPARENTCHECK_CTE, but we stop the recursion after that; then we check for a duplicated in the
--CTE results.
declare @NONPARENTORGANDANCESTORS table
(
ID uniqueidentifier,
PARENTCORPID uniqueidentifier,
PARENTCORPISREPEAT bit
);
with RECURSIVEPARENTCHECK_CTE
as
(
select
ORGANIZATIONDATA.ID,
ORGANIZATIONDATA.PARENTCORPID,
cast(0 as bit) as PARENTCORPISREPEAT
from
dbo.ORGANIZATIONDATA
where
ORGANIZATIONDATA.ID = @NONPARENTORGID
union all
select
ORGANIZATIONDATA.ID,
ORGANIZATIONDATA.PARENTCORPID,
cast
(
case
when ORGANIZATIONDATA.ID = @NONPARENTORGID
then 1
else
0
end
as bit
) as PARENTCORPISREPEAT
from
dbo.ORGANIZATIONDATA
inner join RECURSIVEPARENTCHECK_CTE on RECURSIVEPARENTCHECK_CTE.PARENTCORPID = ORGANIZATIONDATA.ID
where
RECURSIVEPARENTCHECK_CTE.PARENTCORPISREPEAT = 0
)
insert into @NONPARENTORGANDANCESTORS
(
ID,
PARENTCORPID,
PARENTCORPISREPEAT
)
select
RECURSIVEPARENTCHECK_CTE.ID,
RECURSIVEPARENTCHECK_CTE.PARENTCORPID,
RECURSIVEPARENTCHECK_CTE.PARENTCORPISREPEAT
from
RECURSIVEPARENTCHECK_CTE;
if exists (select 1 from @NONPARENTORGANDANCESTORS as NONPARENTORGANDANCESTORS where NONPARENTORGANDANCESTORS.PARENTCORPISREPEAT = 1)
begin
raiserror(N'BBERR_PARENTCOPRRECURSIONDETECTED : The selected parent corporation is already part of the corporate structure as a subsidiary. To make this organization a parent in the corporate structure, first remove it as a subsidiary.', 16, 1);
return 1;
end;
--Set an end date if provided or default to today for all no longer valid relationships after the parent org change
if @OLDPARENTORGID is not null and @SETENDDATE = 1
begin
declare @OLDTABLE table(ID uniqueidentifier);
--If the @NONPARENTORGID record (i.e. the subsidiary) currently has a parent, this @OLDTABLE
--will contain the ID of that parent and all of its parents. This will be empty if the
--@NONPARENTORGID is getting a parent for the first time (i.e. @OLDPARENTORGID is empty guid).
with OldParents (ID,PARENTCORPID)
as
(
--Start with the old parent organization
select OD.ID,OD.PARENTCORPID
from dbo.ORGANIZATIONDATA OD
where OD.ID = @OLDPARENTORGID
union all
--Recursively go up the chain of parents
select OD.ID,OD.PARENTCORPID
from dbo.ORGANIZATIONDATA OD
inner join Oldparents on OldParents.PARENTCORPID = OD.ID
)
insert into @OLDTABLE select ID from OldParents;
-- @ORGCHILDREN will contain all of the children of the @NONPARENTORGID (i.e. the subsidiary)
--as well as their children. The entire subtree beneath the @NONPARENTORGID.
declare @ORGCHILDREN table(ID uniqueidentifier);
with OrgChildren
as
(
--Bug 392756 Now including the @NONPARENTORGID in addition to its descendants.
--There was a second statement that attempted to update the @NONPARENTORGID, but
--it did too much, so instead we can roll it into this statement.
select @NONPARENTORGID as ID
union all
--Recursively go down the chain of children
select OD.ID
from OrgChildren as OC
inner join dbo.ORGANIZATIONDATA OD on OD.PARENTCORPID = OC.ID
)
insert into @ORGCHILDREN select ID from OrgChildren;
--Identifies all of the relationships between descendants (inclusive) and ancestors. Descendants
--are @NONPARENTORGID, any child of @NONPRENTORGID, and any descendent further down the chain.
--Ancestors are the record currently recorded as the parent of @NONPARENTORGID (passed in as @OLDPARENTORGID)
--and its parents up the chain.
--Those relationships could have been created by the @PARENTOFPARENTCHECK setting, the @TOPPARENTCHECK
--setting, or manually. We want to end date all of them when the @SETENDDATE setting is on event though they may
--have different sources. This is the long-standing behavior, but a more robust feature set may have a more nuanced
--approach to dealing with these different relationships; possibly considering type codes.
update dbo.RELATIONSHIP
set ENDDATE = @RELATIONSHIPENDDATE
from dbo.RELATIONSHIP
inner join @ORGCHILDREN OC on OC.ID = RELATIONSHIP.RELATIONSHIPCONSTITUENTID
inner join @OLDTABLE as OLDTABLE on OLDTABLE.ID = RELATIONSHIP.RECIPROCALCONSTITUENTID;
--Bug 392756 Removed a buggy update statement from the fix for Bug 138185 that was modifying all relationships
-- between parents of @NONPARENTORGID and all other constituents.
-- set end date on recognition credits
update dbo.REVENUERECOGNITIONDEFAULT
set
ENDDATE = @RELATIONSHIPENDDATE
from dbo.REVENUERECOGNITIONDEFAULT
inner join @ORGCHILDREN OC on OC.ID = REVENUERECOGNITIONDEFAULT.SOURCECONSTITUENTID
inner join @OLDTABLE as OLDTABLE on OLDTABLE.ID = REVENUERECOGNITIONDEFAULT.RECIPIENTCONSTITUENTID
where
REVENUERECOGNITIONDEFAULT.SOURCECONSTITUENTID = OC.ID;
end
--Build a table of all subsidiaries of the parent and create the relationships based on the RELATIONSHIPCONFIGURATIONCORPORATE table.
declare @TEMPTBL table
(
ID uniqueidentifier,
RELATIONSHIPCONSTITUENTID uniqueidentifier,
RELATIONSHIPTYPECODEID uniqueidentifier,
RECIPROCALCONSTITUENTID uniqueidentifier,
RECIPROCALTYPECODEID uniqueidentifier,
STARTDATE datetime,
ISSPOUSE bit,
PARENTCORPID uniqueidentifier
);
if (@PARENTOFPARENTCHECK = 1 or @TOPPARENTCHECK = 1) and @PARENTORGID is not null
begin
with Parents (ID,PARENTCORPID)
as
(
select OD.ID,OD.PARENTCORPID
from dbo.ORGANIZATIONDATA OD
where OD.ID = @NONPARENTORGID
union all
select OD.ID,OD.PARENTCORPID
from dbo.ORGANIZATIONDATA OD
inner join Parents on Parents.PARENTCORPID = OD.ID
)
insert into @TEMPTBL
select newid() as ID,
@NONPARENTORGID as RELATIONSHIPCONSTITUENTID,
@PARENTOFPARENTSUBSIDIARYORGID as RELATIONSHIPTYPECODEID,
ID as RECIPROCALCONSTITUENTID,
@PARENTOFPARENTORGID as RECIPROCALTYPECODEID,
@STARTDATE,
0 as ISSPOUSE,
PARENTCORPID
from Parents where Parents.ID <> @NONPARENTORGID and Parents.ID <> @PARENTORGID
if @TOPPARENTCHECK = 1
begin
update @TEMPTBL set RELATIONSHIPTYPECODEID = @TOPSUBSIDIARYORGID,RECIPROCALTYPECODEID = @TOPPARENTORGID
where PARENTCORPID is null
end
end
-- Handle the case where only Top parent relationships are being created but not intermediate.
-- Delete all the rows from the temptable that aren't the top parent relationship
if @TOPPARENTCHECK = 1 and @PARENTOFPARENTCHECK = 0
begin
delete from @TEMPTBL
where PARENTCORPID is not null
end
if @ADDINITIALRELATIONSHIP = 1 and @PARENTORGID is not null
begin
insert into @TEMPTBL (ID,RELATIONSHIPCONSTITUENTID,RELATIONSHIPTYPECODEID,RECIPROCALCONSTITUENTID,RECIPROCALTYPECODEID,STARTDATE,ISSPOUSE)
values
(newid(),@NONPARENTORGID,@SUBSIDIARYORGCODEID,@PARENTORGID,@PARENTORGCODEID,@STARTDATE,0);
end
declare @relationship xml
set @relationship = (select
ID,
RELATIONSHIPCONSTITUENTID,
RELATIONSHIPTYPECODEID,
RECIPROCALCONSTITUENTID,
RECIPROCALTYPECODEID,
STARTDATE,
ISSPOUSE
from @TEMPTBL for xml raw('ITEM'),type,elements,root('RELATIONSHIPS'),BINARY BASE64)
if @relationship is not null
begin
--Add relationships
exec USP_RELATIONSHIPS_ADDFROMXML @relationship,null,@CHANGEAGENTID,@CHANGEDATE;
--Add recognition defaults
declare @CONSTITUENTID uniqueidentifier,
@RECIPROCALCONSTITUENTID uniqueidentifier,
@ENDDATE datetime,
@PRIMARYRECOGNITIONDEFAULTEXISTS bit,
@PRIMARYRECOGNITIONDEFAULTMATCHFACTOR decimal(5,2),
@PRIMARYRECOGNITIONDEFAULTTYPECODEID uniqueidentifier,
@RECIPROCALRECOGNITIONDEFAULTEXISTS bit,
@RECIPROCALRECOGNITIONDEFAULTMATCHFACTOR decimal(5,2),
@RECIPROCALRECOGNITIONDEFAULTTYPECODEID uniqueidentifier;
/*Grab a list of all relationships that were added along with any defaults that should be applied*/
declare RELATIONSHIPCURSOR cursor local fast_forward for
select RELATIONSHIP.RELATIONSHIPCONSTITUENTID,
RELATIONSHIP.RECIPROCALCONSTITUENTID,
RELATIONSHIP.STARTDATE,
RELATIONSHIP.ENDDATE,
case when RECOGNITIONRELATIONSHIPDEFAULT.ID is null then 0 else 1 end PRIMARYRECOGNITIONDEFAULTEXISTS,
RECOGNITIONRELATIONSHIPDEFAULT.MATCHFACTOR PRIMARYRECOGNITIONDEFAULTMATCHFACTOR,
RECOGNITIONRELATIONSHIPDEFAULT.REVENUERECOGNITIONTYPECODEID PRIMARYRECOGNITIONDEFAULTTYPECODEID,
case when RECIPDEFAULT.ID is null then 0 else 1 end RECIPROCALRECOGNITIONDEFAULTEXISTS,
RECIPDEFAULT.MATCHFACTOR RECIPROCALRECOGNITIONDEFAULTMATCHFACTOR,
RECIPDEFAULT.REVENUERECOGNITIONTYPECODEID RECIPROCALRECOGNITIONDEFAULTTYPECODEID
from @TEMPTBL temp
inner join dbo.RELATIONSHIP on RELATIONSHIP.ID = temp.ID
left join dbo.RECOGNITIONRELATIONSHIPDEFAULT
on RECOGNITIONRELATIONSHIPDEFAULT.CONSTITUENTTYPECODE = 1 and
RECOGNITIONRELATIONSHIPDEFAULT.RELATIONSHIPTYPECODEID = temp.RELATIONSHIPTYPECODEID
left join dbo.RECOGNITIONRELATIONSHIPDEFAULT RECIPDEFAULT
on RECIPDEFAULT.CONSTITUENTTYPECODE = 1 and
RECIPDEFAULT.RELATIONSHIPTYPECODEID = temp.RECIPROCALTYPECODEID;
open RELATIONSHIPCURSOR;
fetch next from RELATIONSHIPCURSOR into @CONSTITUENTID, @RECIPROCALCONSTITUENTID, @STARTDATE, @ENDDATE,
@PRIMARYRECOGNITIONDEFAULTEXISTS, @PRIMARYRECOGNITIONDEFAULTMATCHFACTOR, @PRIMARYRECOGNITIONDEFAULTTYPECODEID,
@RECIPROCALRECOGNITIONDEFAULTEXISTS, @RECIPROCALRECOGNITIONDEFAULTMATCHFACTOR, @RECIPROCALRECOGNITIONDEFAULTTYPECODEID;
while (@@FETCH_STATUS = 0)
begin
/*Use common code to update recognition credits*/
exec dbo.USP_RECOGNITIONDEFAULTSUPDATE @CONSTITUENTID, @RECIPROCALCONSTITUENTID, @STARTDATE, @ENDDATE,
@PRIMARYRECOGNITIONDEFAULTEXISTS, @PRIMARYRECOGNITIONDEFAULTMATCHFACTOR, @PRIMARYRECOGNITIONDEFAULTTYPECODEID,
@RECIPROCALRECOGNITIONDEFAULTEXISTS, @RECIPROCALRECOGNITIONDEFAULTMATCHFACTOR, @RECIPROCALRECOGNITIONDEFAULTTYPECODEID,
@CHANGEAGENTID, 0;
fetch next from RELATIONSHIPCURSOR into @CONSTITUENTID, @RECIPROCALCONSTITUENTID, @STARTDATE, @ENDDATE,
@PRIMARYRECOGNITIONDEFAULTEXISTS, @PRIMARYRECOGNITIONDEFAULTMATCHFACTOR, @PRIMARYRECOGNITIONDEFAULTTYPECODEID,
@RECIPROCALRECOGNITIONDEFAULTEXISTS, @RECIPROCALRECOGNITIONDEFAULTMATCHFACTOR, @RECIPROCALRECOGNITIONDEFAULTTYPECODEID;
end
close RELATIONSHIPCURSOR;
deallocate RELATIONSHIPCURSOR;
end
return 0;