UFN_EVENTCONFLICT_GETSTAFFRESOURCECONFLICTDETAILS

Get all of the events that are in conflict with the given event conflict by staff resource, includes details.

Return

Return Type
table

Parameters

Parameter Parameter Type Mode Description
@START datetime IN
@END datetime IN
@STAFFRESOURCES xml IN
@IGNORERECORDID uniqueidentifier IN
@IGNORESUBRECORDID uniqueidentifier IN
@IGNORESUPERRECORDID uniqueidentifier IN
@INCLUDEEVENTCONFLICTS bit IN
@INCLUDEITINERARYITEMCONFLICTS bit IN
@INCLUDEITINERARYCONFLICTS bit IN
@OFFSETSTAFFRESOURCES xml IN

Definition

Copy


            CREATE function dbo.UFN_EVENTCONFLICT_GETSTAFFRESOURCECONFLICTDETAILS
            (
                @START datetime,
                @END datetime,
                @STAFFRESOURCES xml,
                @IGNORERECORDID uniqueidentifier = null,
                @IGNORESUBRECORDID uniqueidentifier = null,
                @IGNORESUPERRECORDID uniqueidentifier = null,
                @INCLUDEEVENTCONFLICTS bit = 1,
                @INCLUDEITINERARYITEMCONFLICTS bit = 1,
                @INCLUDEITINERARYCONFLICTS bit = 1,
                @OFFSETSTAFFRESOURCES xml = null
            )
            returns @CONFLICTS TABLE (
                EVENTID uniqueidentifier,
                ITINERARYITEMID uniqueidentifier,
                ITINERARYID uniqueidentifier,
                VOLUNTEERTYPEID uniqueidentifier,
                QUANTITYNEEDED int
            )
            as begin
                -- Take the resource xml passed in and generate a table of resources

                declare @STAFFRESOURCESTABLE table
                (
                    VOLUNTEERTYPEID uniqueidentifier,
                    QUANTITYNEEDED int
                )

                insert into @STAFFRESOURCESTABLE(VOLUNTEERTYPEID, QUANTITYNEEDED)
                    select 
                        T.c.value('(VOLUNTEERTYPEID)[1]','uniqueidentifier'),
                        T.c.value('(QUANTITYNEEDED)[1]','int')
                    from @STAFFRESOURCES.nodes('/STAFFRESOURCES/ITEM') T(c)
                    where T.c.value('(FILLEDBYCODE)[1]','tinyint') = 0 /* Volunteer */

                    union all

                    select
                        T.c.value('(VOLUNTEERTYPEID)[1]','uniqueidentifier'),
                        T.c.value('(QUANTITYNEEDED)[1]','int')
                    from @STAFFRESOURCES.nodes('/EVENTSTAFFRESOURCES/ITEM') T(c)
                    where T.c.value('(FILLEDBYCODE)[1]','tinyint') = 0 /* Volunteer */

                -- If there are no resources to check, return an empty table

                if @@ROWCOUNT = 0
                    return;

                -- Build a table to store resource counts

                declare @STAFFRESOURCESUSED table
                (
                    EVENTID uniqueidentifier,
                    ITINERARYITEMID uniqueidentifier,
                    ITINERARYID uniqueidentifier,
                    VOLUNTEERTYPEID uniqueidentifier,
                    QUANTITYNEEDED int,
                    STARTDATETIME datetime,
                    ENDDATETIME datetime
                )

                -- fill the table based on those events occurring at the same time

                insert into @STAFFRESOURCESUSED
                (
                    EVENTID, 
                    VOLUNTEERTYPEID, 
                    QUANTITYNEEDED,
                    STARTDATETIME,
                    ENDDATETIME
                )
                select 
                    EVENT.ID,
                    EVENTSTAFFRESOURCE.VOLUNTEERTYPEID,
                    EVENTSTAFFRESOURCE.QUANTITYNEEDED,
                    EVENT.STARTDATETIME as STARTDATETIME,
                    EVENT.ENDDATETIME as ENDDATETIME
                from dbo.EVENT
                inner join dbo.EVENTSTAFFRESOURCE on 
                    EVENT.ID = EVENTSTAFFRESOURCE.EVENTID and 
                    EVENTSTAFFRESOURCE.FILLEDBYCODE = 0 /* Volunteer */
                left outer join dbo.PROGRAM on 
                    EVENT.PROGRAMID = PROGRAM.ID
                inner join @STAFFRESOURCESTABLE as EVENTSTAFFRESOURCECONFLICT on 
                    EVENTSTAFFRESOURCECONFLICT.VOLUNTEERTYPEID = EVENTSTAFFRESOURCE.VOLUNTEERTYPEID
                where 
                    (PROGRAM.ISACTIVE = 1 or EVENT.PROGRAMID is null) and
                    (EVENT.ID <> @IGNORERECORDID or (@IGNORERECORDID is null and EVENT.ID is not null)) and
                    (
                        (
                            @START >= EVENT.STARTDATETIME and 
                            @START < EVENT.ENDDATETIME
                        ) or
                        (
                            @END > EVENT.STARTDATETIME and 
                            @END <= EVENT.ENDDATETIME
                        ) or
                        (
                            @START < EVENT.STARTDATETIME and 
                            @END > EVENT.ENDDATETIME
                        )
                    )

                -- fill the table based on those itinerary items occurring at the same time

                insert into @STAFFRESOURCESUSED
                (
                    ITINERARYITEMID, 
                    VOLUNTEERTYPEID, 
                    QUANTITYNEEDED,
                    STARTDATETIME,
                    ENDDATETIME
                )
                select 
                    ITINERARYITEM.ID,
                    ITINERARYITEMSTAFFRESOURCE.VOLUNTEERTYPEID,
                    ITINERARYITEMSTAFFRESOURCE.QUANTITYNEEDED,
                    ITINERARYITEM.STARTDATETIME as STARTDATETIME,
                    ITINERARYITEM.ENDDATETIME as ENDDATETIME
                from dbo.ITINERARYITEM
                inner join dbo.ITINERARY on 
                    ITINERARYITEM.ITINERARYID = ITINERARY.ID
                inner join dbo.SALESORDER on
                    ITINERARY.RESERVATIONID = SALESORDER.ID
                inner join dbo.ITINERARYITEMSTAFFRESOURCE on 
                    ITINERARYITEM.ID = ITINERARYITEMSTAFFRESOURCE.ITINERARYITEMID
                inner join @STAFFRESOURCESTABLE as EVENTSTAFFRESOURCECONFLICT on 
                    EVENTSTAFFRESOURCECONFLICT.VOLUNTEERTYPEID = ITINERARYITEMSTAFFRESOURCE.VOLUNTEERTYPEID
                where  
                    SALESORDER.STATUSCODE <> 5 and -- Make sure the reservation is not cancelled, cancelled resources do not count against total

                    ITINERARYITEM.INVALIDREASONCODE = 0 and -- Make sure that the itinerary item does not have an invalid reason

                    ITINERARYITEM.ITEMTYPECODE <> 3 and -- Make sure the itinerary item is showing as scheduled

                    (ITINERARY.RESERVATIONID <> @IGNORESUPERRECORDID or @IGNORESUPERRECORDID is null) and
                    (
                        (ITINERARYITEM.ID <> @IGNORESUBRECORDID or @IGNORESUBRECORDID is null) or
                        (ITINERARYITEM.ITINERARYID <> @IGNORERECORDID or @IGNORERECORDID is null
                    ) and
                    (
                        (
                            @START >= ITINERARYITEM.STARTDATETIME and 
                            @START < ITINERARYITEM.ENDDATETIME
                        ) or
                        (
                            @END > ITINERARYITEM.STARTDATETIME and 
                            @END <= ITINERARYITEM.ENDDATETIME
                        ) or
                        (
                            @START < ITINERARYITEM.STARTDATETIME and 
                            @END > ITINERARYITEM.ENDDATETIME
                        )
                    )

                -- fill the table based on those itineraries occurring at the same time

                insert into @STAFFRESOURCESUSED
                (
                    ITINERARYID, 
                    VOLUNTEERTYPEID, 
                    QUANTITYNEEDED,
                    STARTDATETIME,
                    ENDDATETIME
                )
                select 
                    ITINERARY.ID,
                    ITINERARYSTAFFRESOURCE.VOLUNTEERTYPEID,
                    ITINERARYSTAFFRESOURCE.QUANTITYNEEDED,
                    ITINERARY.STARTDATETIME as STARTDATETIME,
                    ITINERARY.ENDDATETIME as ENDDATETIME
                from dbo.ITINERARY
                inner join dbo.SALESORDER on
                    ITINERARY.RESERVATIONID = SALESORDER.ID
                inner join ITINERARYSTAFFRESOURCE
                    on ITINERARY.ID = ITINERARYSTAFFRESOURCE.ITINERARYID
                inner join @STAFFRESOURCESTABLE as EVENTSTAFFRESOURCECONFLICT
                    on (EVENTSTAFFRESOURCECONFLICT.VOLUNTEERTYPEID = ITINERARYSTAFFRESOURCE.VOLUNTEERTYPEID)
                where 
                    SALESORDER.STATUSCODE <> 5 and -- Make sure the reservation is not cancelled, cancelled resources do not count against total

                    (ITINERARY.RESERVATIONID <> @IGNORESUPERRECORDID or @IGNORESUPERRECORDID is null) and
                    (
                        @IGNORESUBRECORDID is not null or 
                        (ITINERARY.ID <> @IGNORERECORDID or @IGNORERECORDID is null)
                    ) and
                    (
                        (@START >= ITINERARY.STARTDATETIME and @START < ITINERARY.ENDDATETIME) or
                        (@END > ITINERARY.STARTDATETIME and @END <= ITINERARY.ENDDATETIME) or
                        (@START < ITINERARY.STARTDATETIME and @END > ITINERARY.ENDDATETIME)
                    )


                -- Checking against reservation this is being moved or copied.

                -- Picking up conflicts that would be caused by the whole reservation.

                if @OFFSETSTAFFRESOURCES is not null
                begin
                    delete from @STAFFRESOURCESTABLE;

                    with STAFFRESOURCES_CTE as
                    (
                        select 
                            T.item.value('(VOLUNTEERTYPEID)[1]','uniqueidentifier') as VOLUNTEERTYPEID,
                            T.item.value('(QUANTITYNEEDED)[1]','integer') as QUANTITYNEEDED
                        from @OFFSETSTAFFRESOURCES.nodes('/OFFSETSTAFFRESOURCES/ITEM') T(item)
                        where 
                            (
                                (
                                    T.item.value('(STARTDATETIME)[1]','datetime') <= @START and 
                                    @START < T.item.value('(ENDDATETIME)[1]','datetime')
                                ) or
                                (    
                                    T.item.value('(STARTDATETIME)[1]','datetime') < @END and 
                                    @END <= T.item.value('(ENDDATETIME)[1]','datetime')
                                ) or
                                (
                                    @START < T.item.value('(STARTDATETIME)[1]','datetime') and 
                                    @END > T.item.value('(ENDDATETIME)[1]','datetime')
                                )
                            ) and 
                            T.item.value('(FILLEDBYCODE)[1]','tinyint') = 0 /* Volunteer */
                    )
                    insert into @STAFFRESOURCESTABLE
                    select
                        ST.VOLUNTEERTYPEID,
                        sum(ST.QUANTITYNEEDED)
                    from STAFFRESOURCES_CTE as ST
                    group by ST.VOLUNTEERTYPEID                
                end

                declare @CURRENTUSEDSTAFFRESOURCES table
                (
                    EVENTID uniqueidentifier,
                    ITINERARYITEMID uniqueidentifier,
                    ITINERARYID uniqueidentifier,
                    VOLUNTEERTYPEID uniqueidentifier,
                    QUANTITYNEEDED int
                )                

                declare @THISITINERARYID uniqueidentifier
                declare @THISITINERARYITEMID uniqueidentifier
                declare @THISEVENTID uniqueidentifier
                declare @THISVOLUNTEERTYPEID uniqueidentifier
                declare @THISQUANTITYNEEDED int
                declare @THISTIME datetime
                declare @THISISSTARTTIME bit            

                declare CONFLICTS_CURSOR cursor local fast_forward for
                select
                    ITINERARYID,
                    ITINERARYITEMID,
                    EVENTID,
                    VOLUNTEERTYPEID,
                    QUANTITYNEEDED,
                    TIME,
                    ISSTARTTIME
                from
                (
                    select
                        ITINERARYID,
                        ITINERARYITEMID,
                        EVENTID,
                        VOLUNTEERTYPEID,
                        QUANTITYNEEDED,
                        STARTDATETIME as TIME,
                        1 as ISSTARTTIME
                    from @STAFFRESOURCESUSED

                    union all

                    select
                        ITINERARYID,
                        ITINERARYITEMID,
                        EVENTID,
                        VOLUNTEERTYPEID,
                        QUANTITYNEEDED,
                        ENDDATETIME as TIME,
                        0 as ISSTARTTIME
                    from @STAFFRESOURCESUSED
                ) as T
                order by T.TIME, T.ISSTARTTIME

                open CONFLICTS_CURSOR;

                fetch next from CONFLICTS_CURSOR
                into 
                    @THISITINERARYID
                    @THISITINERARYITEMID
                    @THISEVENTID
                    @THISVOLUNTEERTYPEID,
                    @THISQUANTITYNEEDED,
                    @THISTIME,
                    @THISISSTARTTIME;

                while @@FETCH_STATUS = 0
                begin
                    if @THISISSTARTTIME = 1
                    -- PUSH

                    begin
                        insert into @CURRENTUSEDSTAFFRESOURCES
                        (
                            EVENTID,
                            ITINERARYITEMID,
                            ITINERARYID,
                            VOLUNTEERTYPEID,
                            QUANTITYNEEDED
                        )
                        values
                        (
                            @THISEVENTID,
                            @THISITINERARYITEMID,
                            @THISITINERARYID,
                            @THISVOLUNTEERTYPEID,
                            @THISQUANTITYNEEDED
                        )

                        -- If in conflict, dump @CURRENTUSEDSTAFFRESOURCES into @CONFLICTS

                        -- Not inserting duplicates


                        insert into @CONFLICTS
                        (
                            EVENTID, 
                            ITINERARYITEMID,
                            ITINERARYID,
                            VOLUNTEERTYPEID, 
                            QUANTITYNEEDED
                        )
                        select 
                            STAFFRESOURCESUSED.EVENTID, 
                            STAFFRESOURCESUSED.ITINERARYITEMID,
                            STAFFRESOURCESUSED.ITINERARYID,
                            STAFFRESOURCESUSED.VOLUNTEERTYPEID, 
                            STAFFRESOURCESUSED.QUANTITYNEEDED
                        from @CURRENTUSEDSTAFFRESOURCES as STAFFRESOURCESUSED
                        where 
                            not exists
                            (
                                select 1 from @CONFLICTS
                                where
                                (
                                    [@CONFLICTS].EVENTID = STAFFRESOURCESUSED.EVENTID or
                                    [@CONFLICTS].ITINERARYITEMID = STAFFRESOURCESUSED.ITINERARYITEMID or
                                    [@CONFLICTS].ITINERARYID = STAFFRESOURCESUSED.ITINERARYID
                                ) and
                                [@CONFLICTS].VOLUNTEERTYPEID = STAFFRESOURCESUSED.VOLUNTEERTYPEID
                            ) and
                            STAFFRESOURCESUSED.VOLUNTEERTYPEID in
                            (
                                select OVERALLOCATEDSTAFFRESOURCES.VOLUNTEERTYPEID 
                                from @CURRENTUSEDSTAFFRESOURCES as OVERALLOCATEDSTAFFRESOURCES
                                group by OVERALLOCATEDSTAFFRESOURCES.VOLUNTEERTYPEID
                                having 
                                (
                                    sum(OVERALLOCATEDSTAFFRESOURCES.QUANTITYNEEDED) + 
                                    (
                                        select top 1 STAFFRESOURCES.QUANTITYNEEDED 
                                        from @STAFFRESOURCESTABLE as STAFFRESOURCES 
                                        where STAFFRESOURCES.VOLUNTEERTYPEID = OVERALLOCATEDSTAFFRESOURCES.VOLUNTEERTYPEID
                                    ) > 
                                    (
                                        select VOLUNTEERTYPE.QUANTITY from dbo.VOLUNTEERTYPE 
                                        where VOLUNTEERTYPE.ID = OVERALLOCATEDSTAFFRESOURCES.VOLUNTEERTYPEID
                                    )
                                )
                            )

                    end
                    else
                    -- POP

                    -- Do not need to check for conflicts as we are actually decrementing the count

                    begin
                        delete from @CURRENTUSEDSTAFFRESOURCES
                        where
                        (
                            @THISEVENTID = [@CURRENTUSEDSTAFFRESOURCES].EVENTID or
                            @THISITINERARYITEMID = [@CURRENTUSEDSTAFFRESOURCES].ITINERARYITEMID or
                            @THISITINERARYID = [@CURRENTUSEDSTAFFRESOURCES].ITINERARYID
                        ) and
                        @THISVOLUNTEERTYPEID = [@CURRENTUSEDSTAFFRESOURCES].VOLUNTEERTYPEID
                    end

                    fetch next from CONFLICTS_CURSOR
                    into 
                        @THISITINERARYID
                        @THISITINERARYITEMID
                        @THISEVENTID
                        @THISVOLUNTEERTYPEID,
                        @THISQUANTITYNEEDED,
                        @THISTIME,
                        @THISISSTARTTIME;
                end

                close CONFLICTS_CURSOR;
                deallocate CONFLICTS_CURSOR;

                delete from @CONFLICTS
                where
                    @INCLUDEEVENTCONFLICTS = 0 and EVENTID is not null or
                    @INCLUDEITINERARYCONFLICTS = 0 and ITINERARYID is not null or
                    @INCLUDEITINERARYITEMCONFLICTS = 0 and ITINERARYITEMID is not null

                return;

            end