UFN_CONFLICTCHECK_GETRESOURCECONFLICTS

Get all of the records that are in conflict with the given resources.

Return

Return Type
table

Parameters

Parameter Parameter Type Mode Description
@START datetime IN
@END datetime IN
@RESOURCES xml IN
@OFFSETRESOURCES xml IN
@SUPERRECORDID uniqueidentifier IN
@RECORDID uniqueidentifier IN
@SUBRECORDID uniqueidentifier IN
@IGNORESUPERRECORD bit IN
@IGNORERECORD bit IN
@IGNORESUBRECORD bit IN
@IGNORERECORDSUBRECORDS bit IN

Definition

Copy


        CREATE function dbo.UFN_CONFLICTCHECK_GETRESOURCECONFLICTS
        (
            @START datetime,
            @END datetime,
            @RESOURCES xml,
            @OFFSETRESOURCES xml = null,
            @SUPERRECORDID uniqueidentifier = null,
            @RECORDID uniqueidentifier = null,
            @SUBRECORDID uniqueidentifier = null,
            @IGNORESUPERRECORD bit = 1,
            @IGNORERECORD bit = 1,
            @IGNORESUBRECORD bit = 1,
            @IGNORERECORDSUBRECORDS bit = 1
        )
        returns @CONFLICTS TABLE
        (
            EVENTID uniqueidentifier,
            ITINERARYITEMID uniqueidentifier,
            ITINERARYID uniqueidentifier,
            RESOURCEID uniqueidentifier,
            QUANTITYNEEDED int
        )
        as
        begin             

            -- Take the resource xml passed in and generate a table of resources

            declare @RESOURCESTABLE table
            (
                RESOURCEID uniqueidentifier,
                QUANTITYNEEDED int
            )

            insert into @RESOURCESTABLE
            (RESOURCEID, QUANTITYNEEDED)
            select 
                T.c.value('(RESOURCEID)[1]','uniqueidentifier'),
                T.c.value('(QUANTITYNEEDED)[1]','int')
            from @RESOURCES.nodes('/RESOURCES/ITEM') T(c)

            if @RECORDID is not null
            begin
                declare @VISITORCOUNT int
                set @VISITORCOUNT = isnull((
                                        select sum(ITINERARYATTENDEE.QUANTITY)
                                        from dbo.ITINERARYATTENDEE
                                        where ITINERARYID = @RECORDID
                                    ),0);
                update @RESOURCESTABLE set
                    QUANTITYNEEDED = dbo.UFN_RESOURCE_CALCULATEPERTICKETQUANTITY_2(@VISITORCOUNT * RESOURCE.PERTICKETQUANTITY, RESOURCE.PERTICKETDIVISOR)
                from dbo.RESOURCE
                where
                    RESOURCE.ID = [@RESOURCESTABLE].RESOURCEID and
                    -- Special checks for Itinerary Edit, Reservation Add, Group Checkin

                    -- already set this up because of attendee quantity change

                    [@RESOURCESTABLE].QUANTITYNEEDED = 0 and 
                    RESOURCE.ISPERTICKETITEM = 1
            end

            insert into @RESOURCESTABLE
            (RESOURCEID, QUANTITYNEEDED)
            select 
                T.c.value('(RESOURCEID)[1]','uniqueidentifier'),
                T.c.value('(QUANTITYNEEDED)[1]','int')
            from @RESOURCES.nodes('/EVENTRESOURCES/ITEM') T(c)

            -- Build a table to store resource counts

            declare @RESOURCESUSED table
            (
                EVENTID uniqueidentifier,
                ITINERARYITEMID uniqueidentifier,
                ITINERARYID uniqueidentifier,
                RESOURCEID uniqueidentifier,
                QUANTITYNEEDED int,
                STARTDATETIME datetime,
                ENDDATETIME datetime
            )

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

            insert into @RESOURCESUSED
            (
                EVENTID, 
                RESOURCEID, 
                QUANTITYNEEDED,
                STARTDATETIME,
                ENDDATETIME
            )
            select 
                EVENT.ID,
                EVENTRESOURCE.RESOURCEID,
                EVENTRESOURCE.QUANTITYNEEDED,
                EVENT.STARTDATETIME as STARTDATETIME,
                EVENT.ENDDATETIME as ENDDATETIME
            from dbo.EVENT
            inner join dbo.EVENTRESOURCE on EVENT.ID = EVENTRESOURCE.EVENTID
            inner join dbo.RESOURCE on 
                (EVENTRESOURCE.RESOURCEID = RESOURCE.ID) and (RESOURCE.TYPECODE = 0) --A non-consumable rsource

            left outer join dbo.PROGRAM on 
                EVENT.PROGRAMID = PROGRAM.ID
            inner join @RESOURCESTABLE as EVENTRESOURCECONFLICT on 
                EVENTRESOURCECONFLICT.RESOURCEID = EVENTRESOURCE.RESOURCEID
            where 
                (PROGRAM.ISACTIVE = 1 or EVENT.PROGRAMID is null) and
                (@IGNORERECORD = 0 or @RECORDID is null or EVENT.ID <> @RECORDID) 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 @RESOURCESUSED
            (
                ITINERARYITEMID, 
                RESOURCEID, 
                QUANTITYNEEDED,
                STARTDATETIME,
                ENDDATETIME
            )
            select 
                ITINERARYITEM.ID,
                ITINERARYITEMRESOURCE.RESOURCEID,
                case RESOURCE.ISPERTICKETITEM
                    when 0 then
                        ITINERARYITEMRESOURCE.QUANTITYNEEDED
                    else
                        dbo.UFN_RESOURCE_CALCULATEPERTICKETQUANTITY_2(COALESCE((select sum(ITINERARYATTENDEE.QUANTITY) from dbo.ITINERARYATTENDEE where ITINERARYATTENDEE.ITINERARYID = ITINERARY.ID),0) * ITINERARYITEMRESOURCE.PERTICKETQUANTITY, ITINERARYITEMRESOURCE.PERTICKETDIVISOR)
                end as 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.ITINERARYITEMRESOURCE on 
                ITINERARYITEM.ID = ITINERARYITEMRESOURCE.ITINERARYITEMID
            inner join dbo.RESOURCE on 
                ITINERARYITEMRESOURCE.RESOURCEID = RESOURCE.ID and 
                RESOURCE.TYPECODE = 0 --A non-consumable resource

            inner join @RESOURCESTABLE as EVENTRESOURCECONFLICT on 
                EVENTRESOURCECONFLICT.RESOURCEID = ITINERARYITEMRESOURCE.RESOURCEID
            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

                (@IGNORESUPERRECORD = 0 or @SUPERRECORDID is null or ITINERARY.RESERVATIONID <> @SUPERRECORDID) and
                (
                    not (ITINERARYITEM.ITINERARYID = @RECORDID and @IGNORERECORDSUBRECORDS = 1) and
                    (@IGNORESUBRECORD = 0 or @SUBRECORDID is null or ITINERARYITEM.ID <> @SUBRECORDID
                ) 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 @RESOURCESUSED
            (
                ITINERARYID, 
                RESOURCEID, 
                QUANTITYNEEDED,
                STARTDATETIME,
                ENDDATETIME
            )
            select 
                ITINERARY.ID,
                ITINERARYRESOURCE.RESOURCEID,
                case RESOURCE.ISPERTICKETITEM
                    when 0 then
                        ITINERARYRESOURCE.QUANTITYNEEDED
                    else
                        dbo.UFN_RESOURCE_CALCULATEPERTICKETQUANTITY_2(COALESCE((select sum(ITINERARYATTENDEE.QUANTITY) from dbo.ITINERARYATTENDEE where ITINERARYATTENDEE.ITINERARYID = ITINERARYRESOURCE.ITINERARYID),0) * ITINERARYRESOURCE.PERTICKETQUANTITY, ITINERARYRESOURCE.PERTICKETDIVISOR)
                end as QUANTITYNEEDED,
                ITINERARY.STARTDATETIME as STARTDATETIME,
                ITINERARY.ENDDATETIME as ENDDATETIME
            from dbo.ITINERARY
            inner join dbo.SALESORDER on
                ITINERARY.RESERVATIONID = SALESORDER.ID
            inner join dbo.ITINERARYRESOURCE on 
                ITINERARY.ID = ITINERARYRESOURCE.ITINERARYID
            inner join dbo.RESOURCE on 
                ITINERARYRESOURCE.RESOURCEID = RESOURCE.ID and 
                RESOURCE.TYPECODE = 0 --A non-consumable resource

            inner join @RESOURCESTABLE as EVENTRESOURCECONFLICT on 
                EVENTRESOURCECONFLICT.RESOURCEID = ITINERARYRESOURCE.RESOURCEID
            where
                SALESORDER.STATUSCODE <> 5 and -- Make sure the reservation is not cancelled, cancelled resources do not count against total

                (@IGNORERECORD = 0 or @RECORDID is null or ITINERARY.ID <> @RECORDID) and
                (@IGNORESUPERRECORD = 0 or @SUPERRECORDID is null or ITINERARY.RESERVATIONID <> @SUPERRECORDID) and
                (
                    (@START >= ITINERARY.STARTDATETIME and @START < ITINERARY.ENDDATETIME) or
                    (@END > ITINERARY.STARTDATETIME and @END <= ITINERARY.ENDDATETIME) or
                    (@START < ITINERARY.STARTDATETIME and @END > ITINERARY.ENDDATETIME) or    
                    -- Checking against an itinerary that has a time extended by the itinerary item

                    (@RECORDID is not null and @RECORDID = ITINERARY.ID)
                )

            -- Set itinerary times to be within itinerary item window when changing time of itinerary

            -- Times outside of @START and @END are not an issue against conflicts

            if @RECORDID is not null and @SUBRECORDID is not null and @IGNORERECORD = 0
                update @RESOURCESUSED set
                    STARTDATETIME = @START,
                    ENDDATETIME = @END
                where
                    ITINERARYID is not null and
                    ITINERARYID = @RECORDID

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

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

            if @OFFSETRESOURCES is not null
            begin
                with RESOURCES_CTE as
                (
                    select 
                        T.item.value('(ITINERARYID)[1]','uniqueidentifier') as ITINERARYID,
                        T.item.value('(ITINERARYITEMID)[1]','uniqueidentifier') as ITINERARYITEMID,
                        T.item.value('(RESOURCEID)[1]','uniqueidentifier') as RESOURCEID,
                        T.item.value('(QUANTITYNEEDED)[1]','integer') as QUANTITYNEEDED,
                        T.item.value('(STARTDATETIME)[1]','datetime') as STARTDATETIME,
                        T.item.value('(ENDDATETIME)[1]','datetime') as ENDDATETIME
                    from @OFFSETRESOURCES.nodes('/OFFSETRESOURCES/ITEM') T(item)
                    where 
                        (
                            @START >= T.item.value('(STARTDATETIME)[1]','datetime') and 
                            @START < T.item.value('(ENDDATETIME)[1]','datetime')
                        ) or
                        (
                            @END > T.item.value('(STARTDATETIME)[1]','datetime') and 
                            @END <= T.item.value('(ENDDATETIME)[1]','datetime')
                        ) or
                        (
                            @START < T.item.value('(STARTDATETIME)[1]','datetime') and 
                            @END > T.item.value('(ENDDATETIME)[1]','datetime')
                        )
                )
                insert into @RESOURCESUSED
                (
                    ITINERARYID,
                    ITINERARYITEMID,
                    RESOURCEID, 
                    QUANTITYNEEDED,
                    STARTDATETIME,
                    ENDDATETIME
                )
                select 
                    case 
                        when ITINERARYITEMID is null or ITINERARYITEMID = '00000000-0000-0000-0000-000000000000' 
                            then ITINERARYID
                        else null 
                    end as ITINERARYID,
                    ITINERARYITEMID,
                    RESOURCEID,
                    QUANTITYNEEDED,
                    STARTDATETIME,
                    ENDDATETIME
                from RESOURCES_CTE RE
                where
                    -- Resources already in itinerary should be in RESOURCESTABLE 

                    (
                        @IGNORERECORD = 0 or -- Double counting resources if not ignoring record

                        @RECORDID is null or
                        ITINERARYID is null or
                        @SUBRECORDID is not null or 
                        (
                            ITINERARYITEMID is not null and
                            ITINERARYITEMID <> '00000000-0000-0000-0000-000000000000'
                        ) or
                        ITINERARYID <> @RECORDID
                    ) and
                    (
                        @IGNORESUBRECORD = 0 or
                        @SUBRECORDID is null or  
                        (
                            ITINERARYITEMID is null or
                            ITINERARYITEMID = '00000000-0000-0000-0000-000000000000'
                        ) or
                        ITINERARYITEMID <> @SUBRECORDID
                    )

            end

            declare @CURRENTUSEDRESOURCES table
            (
                EVENTID uniqueidentifier,
                ITINERARYITEMID uniqueidentifier,
                ITINERARYID uniqueidentifier,
                RESOURCEID uniqueidentifier,
                QUANTITYNEEDED int
            )                

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

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

                union all

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

            open CONFLICTS_CURSOR;

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

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

                begin
                    insert into @CURRENTUSEDRESOURCES
                    (
                        EVENTID,
                        ITINERARYITEMID,
                        ITINERARYID,
                        RESOURCEID,
                        QUANTITYNEEDED
                    )
                    values
                    (
                        @THISEVENTID,
                        @THISITINERARYITEMID,
                        @THISITINERARYID,
                        @THISRESOURCEID,
                        @THISQUANTITYNEEDED
                    );

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

                    -- Not inserting duplicates


                    with RESOURCETOTAL_CTE as
                    (
                        select
                            RESOURCEID,
                            sum(QUANTITYNEEDED) as QUANTITYNEEDED,
                            count(RESOURCEID) as RESOURCECOUNT
                        from
                        (
                            select
                                RESOURCEID,
                                QUANTITYNEEDED
                            from @CURRENTUSEDRESOURCES

                            union all

                            select
                                RESOURCEID,
                                QUANTITYNEEDED
                            from @RESOURCESTABLE                        
                        ) as T
                        group by T.RESOURCEID
                    )                    
                    insert into @CONFLICTS
                    (
                        EVENTID, 
                        ITINERARYITEMID,
                        ITINERARYID,
                        RESOURCEID, 
                        QUANTITYNEEDED
                    )
                    select 
                        RESOURCESUSED.EVENTID, 
                        RESOURCESUSED.ITINERARYITEMID,
                        RESOURCESUSED.ITINERARYID,
                        RESOURCESUSED.RESOURCEID, 
                        RESOURCESUSED.QUANTITYNEEDED
                    from @CURRENTUSEDRESOURCES as RESOURCESUSED
                    inner join RESOURCETOTAL_CTE RESOURCETOTAL on
                        RESOURCETOTAL.RESOURCEID = RESOURCESUSED.RESOURCEID
                    inner join dbo.RESOURCE on
                        RESOURCESUSED.RESOURCEID = RESOURCE.ID 
                    where 
                        not exists
                        (
                            select 1 from @CONFLICTS
                            where
                            (
                                [@CONFLICTS].EVENTID = RESOURCESUSED.EVENTID or
                                [@CONFLICTS].ITINERARYITEMID = RESOURCESUSED.ITINERARYITEMID or
                                [@CONFLICTS].ITINERARYID = RESOURCESUSED.ITINERARYID
                            ) and
                            [@CONFLICTS].RESOURCEID = RESOURCESUSED.RESOURCEID
                        ) and
                        RESOURCETOTAL.QUANTITYNEEDED > RESOURCE.QUANTITY and
                        RESOURCETOTAL.RESOURCECOUNT > 1

                end
                else
                -- POP

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

                begin
                    delete from @CURRENTUSEDRESOURCES
                    where
                    (
                        @THISEVENTID = [@CURRENTUSEDRESOURCES].EVENTID or
                        @THISITINERARYITEMID = [@CURRENTUSEDRESOURCES].ITINERARYITEMID or
                        @THISITINERARYID = [@CURRENTUSEDRESOURCES].ITINERARYID
                    ) and
                    @THISRESOURCEID = [@CURRENTUSEDRESOURCES].RESOURCEID
                end

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

            close CONFLICTS_CURSOR;
            deallocate CONFLICTS_CURSOR;

            return;
        end