USP_ORGANIZATIONHIERARCHY_UPDATEFROMXML_2

Updates the stored organization hierarchy and its positions from the given xml.

Parameters

Parameter Parameter Type Mode Description
@XML xml IN
@CHANGEAGENTID uniqueidentifier IN
@CHANGEDATE datetime IN

Definition

Copy


create procedure dbo.USP_ORGANIZATIONHIERARCHY_UPDATEFROMXML_2
(
  @XML xml,
  @CHANGEAGENTID uniqueidentifier = null,
  @CHANGEDATE datetime = null
)
as
  set nocount on;

  /*This is a customized version of the UPDATEFROMXML to accommodate the same relations structure.
    Be warned that the insert/update/delete order is different
  */

  if @CHANGEAGENTID is null
    exec USP_CHANGEAGENT_GETORCREATECHANGEAGENT @CHANGEAGENTID output;

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

  declare @IDOC int;
  exec sp_xml_preparedocument @IDOC output, @XML;

  declare @ORGHIERARCHY table
  (
    ID uniqueidentifier,
    PARENTID uniqueidentifier,
    NAME nvarchar(100),
    SITEID uniqueidentifier,
    BUSINESSUNITCODEID uniqueidentifier,
    SEQUENCE int
  );

  insert into
    @ORGHIERARCHY
  select
    ID,
    PARENTID,
    NAME,
    SITEID,
    BUSINESSUNITCODEID,
    SEQUENCE
  from
    openxml(@IDOC, '/ORGANIZATIONHIERARCHY/ITEM')
    with
    (
      ID uniqueidentifier 'ID',
      PARENTID uniqueidentifier 'PARENTID',
      NAME nvarchar(100) 'NAME',
      SITEID uniqueidentifier 'SITEID',
      BUSINESSUNITCODEID uniqueidentifier 'BUSINESSUNITCODEID',
      SEQUENCE int 'SEQUENCE'
    );

  declare @ORGPOSITIONHOLDERS table
  (
    ID uniqueidentifier,
    POSITIONID uniqueidentifier,
    CONSTITUENTID uniqueidentifier,
    DATEFROM datetime,
    DATETO datetime,
    BUSINESSUNITCODEID uniqueidentifier
  );

  insert into
    @ORGPOSITIONHOLDERS
  select
    ID,
    POSITIONID,
    CONSTITUENTID,
    DATEFROM,
    DATETO,
    BUSINESSUNITCODEID
  from
    openxml(@IDOC, '/ORGANIZATIONHIERARCHY/ITEM/POSITIONHOLDERS/ITEM')
    with
    (
      ID uniqueidentifier 'ID',
      POSITIONID uniqueidentifier '../../ID',
      CONSTITUENTID uniqueidentifier 'CONSTITUENTID',
      DATEFROM datetime 'DATEFROM',
      DATETO datetime 'DATETO',
      BUSINESSUNITCODEID uniqueidentifier 'BUSINESSUNITCODEID'
    );

  exec sp_xml_removedocument @IDOC;

  update
    @ORGHIERARCHY
  set
    ID = newid()
  where
    (ID is null) or
    (ID = '00000000-0000-0000-0000-000000000000');

  if @@Error <> 0
    return 1;

  update
    @ORGPOSITIONHOLDERS
  set
    ID = newid()
  where
    (ID is null) or
    (ID = '00000000-0000-0000-0000-000000000000');

  insert into dbo.ORGANIZATIONHIERARCHY
  (
    ID,
    PARENTID,
    SEQUENCE,
    ADDEDBYID,
    CHANGEDBYID,
    DATEADDED,
    DATECHANGED
  )
  select
    ID,
    PARENTID,
    SEQUENCE,
    @CHANGEAGENTID,
    @CHANGEAGENTID,
    @CHANGEDATE,
    @CHANGEDATE
  from
    @ORGHIERARCHY as TEMP
  where
    not exists (select ID from dbo.ORGANIZATIONHIERARCHY as DATA where DATA.ID = TEMP.ID);

  if @@Error <> 0
    return 2;

  update
    ORGANIZATIONHIERARCHY
  set
    ORGANIZATIONHIERARCHY.PARENTID = TEMP.PARENTID,
    ORGANIZATIONHIERARCHY.SEQUENCE = TEMP.SEQUENCE,
    ORGANIZATIONHIERARCHY.CHANGEDBYID = @CHANGEAGENTID,
    ORGANIZATIONHIERARCHY.DATECHANGED = @CHANGEDATE
  from
    dbo.ORGANIZATIONHIERARCHY
  inner join
    @ORGHIERARCHY as TEMP on ORGANIZATIONHIERARCHY.ID = TEMP.ID
  where
    (ORGANIZATIONHIERARCHY.PARENTID <> TEMP.PARENTID) or 
    (ORGANIZATIONHIERARCHY.PARENTID is null and TEMP.PARENTID is not null) or 
    (ORGANIZATIONHIERARCHY.PARENTID is not null and TEMP.PARENTID is null) or 
    (ORGANIZATIONHIERARCHY.SEQUENCE <> TEMP.SEQUENCE) or 
    (ORGANIZATIONHIERARCHY.SEQUENCE is null and TEMP.SEQUENCE is not null) or 
    (ORGANIZATIONHIERARCHY.SEQUENCE is not null and TEMP.SEQUENCE is null)

  if @@Error <> 0
    return 3;    

  declare @CONTEXTCACHE varbinary(128);
  declare @LOCALERROR int;

  set @CONTEXTCACHE = context_info();

  if not @CHANGEAGENTID is null
    set context_info @CHANGEAGENTID;

  -- delete any items that no longer exist in the XML table

  delete from
    dbo.ORGANIZATIONHIERARCHY
  where
    ORGANIZATIONHIERARCHY.ID not in (select ID from @ORGHIERARCHY);

  delete from
    dbo.ORGANIZATIONPOSITIONHOLDER
  where
    ORGANIZATIONPOSITIONHOLDER.ID not in (select ID from @ORGPOSITIONHOLDERS);

  select @LOCALERROR = @@error;

  if not @CONTEXTCACHE is null
    set context_info @CONTEXTCACHE;

  if @LOCALERROR <> 0
    return 4;

  update
    ORGANIZATIONPOSITION
  set
    ORGANIZATIONPOSITION.NAME = TEMP.NAME,
    ORGANIZATIONPOSITION.SITEID = TEMP.SITEID,
    ORGANIZATIONPOSITION.BUSINESSUNITCODEID = TEMP.BUSINESSUNITCODEID,
    ORGANIZATIONPOSITION.CHANGEDBYID = @CHANGEAGENTID,
    ORGANIZATIONPOSITION.DATECHANGED = @CHANGEDATE
  from
    dbo.ORGANIZATIONPOSITION
  inner join
    @ORGHIERARCHY as TEMP on TEMP.ID = ORGANIZATIONPOSITION.ID
  where
    (ORGANIZATIONPOSITION.NAME <> TEMP.NAME) or
    (ORGANIZATIONPOSITION.NAME is null and TEMP.NAME is not null) or
    (ORGANIZATIONPOSITION.NAME is not null and TEMP.NAME is null) or
    (ORGANIZATIONPOSITION.SITEID <> TEMP.SITEID) or
    (ORGANIZATIONPOSITION.SITEID is null and TEMP.SITEID is not null) or
    (ORGANIZATIONPOSITION.SITEID is not null and TEMP.SITEID is null) or
    (ORGANIZATIONPOSITION.BUSINESSUNITCODEID <> TEMP.BUSINESSUNITCODEID) or
    (ORGANIZATIONPOSITION.BUSINESSUNITCODEID is null and TEMP.BUSINESSUNITCODEID is not null) or
    (ORGANIZATIONPOSITION.BUSINESSUNITCODEID is not null and TEMP.BUSINESSUNITCODEID is null)

  if @@Error <> 0
    return 3;    

  insert into dbo.ORGANIZATIONPOSITION
  (
    ID,
    NAME,
    SITEID,
    BUSINESSUNITCODEID,
    ADDEDBYID,
    CHANGEDBYID,
    DATEADDED,
    DATECHANGED
  )
  select
    ID,
    NAME,
    SITEID,
    BUSINESSUNITCODEID,
    @CHANGEAGENTID,
    @CHANGEAGENTID,
    @CHANGEDATE,
    @CHANGEDATE
  from
    @ORGHIERARCHY as TEMP
  where
    not exists (select ID from dbo.ORGANIZATIONPOSITION as DATA where DATA.ID = TEMP.ID)

  -- update the items that exist in the XML table and the db

  -- we must update items based on how the dates are changed

  -- decreases in [DATETO] first

  -- changes to [DATEFROM] next

  -- increases in [DATETO] last

  -- changes to position and constituent are not allowed

  declare @UPDATEID uniqueidentifier;
  declare @DATEFROM datetime;
  declare @DATETO datetime;

  declare CUR_UPDATES cursor local fast_forward for

  select
    TEMP.ID,
    TEMP.DATEFROM,
    TEMP.DATETO
  from
    dbo.ORGANIZATIONPOSITIONHOLDER
  inner join
    @ORGPOSITIONHOLDERS as TEMP on TEMP.ID = ORGANIZATIONPOSITIONHOLDER.ID
  where
    (ORGANIZATIONPOSITIONHOLDER.DATEFROM <> TEMP.DATEFROM) or
    (ORGANIZATIONPOSITIONHOLDER.DATEFROM is null and TEMP.DATEFROM is not null) or
    (ORGANIZATIONPOSITIONHOLDER.DATEFROM is not null and TEMP.DATEFROM is null) or
    (ORGANIZATIONPOSITIONHOLDER.DATETO <> TEMP.DATETO) or
    (ORGANIZATIONPOSITIONHOLDER.DATETO is null and TEMP.DATETO is not null) or
    (ORGANIZATIONPOSITIONHOLDER.DATETO is not null and TEMP.DATETO is null)
  order by 
    case
      when TEMP.DATETO < ORGANIZATIONPOSITIONHOLDER.DATETO
        then 0
      else
        case
          when TEMP.DATETO > ORGANIZATIONPOSITIONHOLDER.DATETO
            then 2
          else 1
        end 
    end,
    TEMP.DATEFROM;

  open CUR_UPDATES;

  fetch next from CUR_UPDATES into @UPDATEID, @DATEFROM, @DATETO;
  while @@FETCH_STATUS = 0
  begin
    update
      dbo.ORGANIZATIONPOSITIONHOLDER
    set
      DATEFROM = @DATEFROM,
      DATETO = @DATETO,
      CHANGEDBYID = @CHANGEAGENTID,
      DATECHANGED = @CHANGEDATE
    where
      ORGANIZATIONPOSITIONHOLDER.ID = @UPDATEID;

    fetch next from CUR_UPDATES into @UPDATEID, @DATEFROM, @DATETO;
  end

  close CUR_UPDATES;
  deallocate CUR_UPDATES;

  if @@Error <> 0
    return 3;

  -- insert new items

  insert into dbo.ORGANIZATIONPOSITIONHOLDER
  (
    ID,
    POSITIONID,
    CONSTITUENTID,
    DATEFROM,
    DATETO,
    ADDEDBYID, 
    CHANGEDBYID, 
    DATEADDED, 
    DATECHANGED
  )
  select
    ID,
    POSITIONID,
    CONSTITUENTID,
    DATEFROM,
    DATETO,
    @CHANGEAGENTID,
    @CHANGEAGENTID,
    @CHANGEDATE,
    @CHANGEDATE
  from
    @ORGPOSITIONHOLDERS as TEMP
  where
    not exists (select ID from dbo.ORGANIZATIONPOSITIONHOLDER as DATA where DATA.ID = TEMP.ID)

  if @@Error <> 0
    return 4;

  return 0;