UFN_CONFLICTCHECK_GETSTAFFRESOURCECONFLICTSFORMULTIPLETIMES
For a large amount of non overlapping events with dates, return all events with staff resource conflicts.
Return
Return Type |
---|
table |
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@EVENTDATES | xml | IN | |
@STAFFRESOURCES | xml | IN |
Definition
Copy
CREATE function dbo.UFN_CONFLICTCHECK_GETSTAFFRESOURCECONFLICTSFORMULTIPLETIMES
(
@EVENTDATES xml,
@STAFFRESOURCES xml
)
returns @CONFLICTS TABLE
(
EVENTID uniqueidentifier
)
as
begin
declare @EVENTDATESTABLE table
(
EVENTID uniqueidentifier,
STARTDATETIME datetime,
ENDDATETIME datetime
)
insert into @EVENTDATESTABLE
select
T.c.value('(EVENTID)[1]','uniqueidentifier') as 'EVENTID',
T.c.value('(STARTDATETIME)[1]','datetime') as 'STARTDATETIME',
T.c.value('(ENDDATETIME)[1]','datetime') as 'ENDDATETIME'
from @EVENTDATES.nodes('/EVENTDATES/ITEM') T(c)
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 */
if (select count(1) from @STAFFRESOURCESTABLE) = 0
return;
-- Build a table to store resource counts
declare @STAFFRESOURCESUSED table
(
SUPEREVENTID uniqueidentifier,
EVENTID uniqueidentifier,
ITINERARYID uniqueidentifier,
ITINERARYITEMID uniqueidentifier,
VOLUNTEERTYPEID uniqueidentifier,
QUANTITYNEEDED int,
STARTDATETIME datetime,
ENDDATETIME datetime
)
insert into @STAFFRESOURCESUSED
(
SUPEREVENTID,
EVENTID,
ITINERARYID,
ITINERARYITEMID,
VOLUNTEERTYPEID,
QUANTITYNEEDED,
STARTDATETIME,
ENDDATETIME
)
select
EVENTDATES.EVENTID as SUPEREVENTID,
STAFFRESOURCES.EVENTID,
STAFFRESOURCES.ITINERARYID,
STAFFRESOURCES.ITINERARYITEMID,
STAFFRESOURCES.VOLUNTEERTYPEID,
STAFFRESOURCES.QUANTITYNEEDED,
STAFFRESOURCES.STARTDATETIME,
STAFFRESOURCES.ENDDATETIME
from
(
select
EVENT.ID as EVENTID,
null as ITINERARYID,
null as ITINERARYITEMID,
EVENTSTAFFRESOURCE.VOLUNTEERTYPEID as VOLUNTEERTYPEID,
EVENTSTAFFRESOURCE.QUANTITYNEEDED as QUANTITYNEEDED,
EVENT.STARTDATETIME as STARTDATETIME,
EVENT.ENDDATETIME as ENDDATETIME
from dbo.EVENT
inner join dbo.EVENTSTAFFRESOURCE on EVENT.ID = EVENTSTAFFRESOURCE.EVENTID
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)
union all
-- itinerary items
select
null as EVENTID,
null as ITINERARYID,
ITINERARYITEM.ID as ITINERARYITEMID,
ITINERARYITEMSTAFFRESOURCE.VOLUNTEERTYPEID as VOLUNTEERTYPEID,
ITINERARYITEMSTAFFRESOURCE.QUANTITYNEEDED 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.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 -- Make sure the itinerary item is showing as scheduled
union all
-- itineraries
select
null as EVENTID,
ITINERARY.ID as ITINERARYID,
null as ITINERARYITEMID,
ITINERARYSTAFFRESOURCE.VOLUNTEERTYPEID as VOLUNTEERTYPEID,
ITINERARYSTAFFRESOURCE.QUANTITYNEEDED as 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 -- Make sure the reservation is not cancelled, cancelled resources do not count against total
) as STAFFRESOURCES
inner join @EVENTDATESTABLE as EVENTDATES on
(
(EVENTDATES.STARTDATETIME >= STAFFRESOURCES.STARTDATETIME and EVENTDATES.STARTDATETIME < STAFFRESOURCES.ENDDATETIME) or
(EVENTDATES.ENDDATETIME > STAFFRESOURCES.STARTDATETIME and EVENTDATES.ENDDATETIME <= STAFFRESOURCES.ENDDATETIME) or
(EVENTDATES.STARTDATETIME < STAFFRESOURCES.STARTDATETIME and EVENTDATES.ENDDATETIME > STAFFRESOURCES.ENDDATETIME)
)
declare @CURRENTUSEDSTAFFRESOURCES table
(
SUPEREVENTID uniqueidentifier,
EVENTID uniqueidentifier,
ITINERARYITEMID uniqueidentifier,
ITINERARYID uniqueidentifier,
VOLUNTEERTYPEID uniqueidentifier,
QUANTITYNEEDED int
)
declare @THISSUPEREVENTID uniqueidentifier
declare @THISITINERARYID uniqueidentifier
declare @THISITINERARYITEMID uniqueidentifier
declare @THISEVENTID uniqueidentifier
declare @THISVOLUNTEERTYPEID uniqueidentifier
declare @THISQUANTITYNEEDED int
declare @THISTIME datetime
declare @THISISSTARTTIME bit
declare @CURRENTEVENTID uniqueidentifier
declare CONFLICTS_CURSOR cursor local fast_forward for
select
SUPEREVENTID,
ITINERARYID,
ITINERARYITEMID,
EVENTID,
VOLUNTEERTYPEID,
QUANTITYNEEDED,
TIME,
ISSTARTTIME
from
(
select
SUPEREVENTID,
ITINERARYID,
ITINERARYITEMID,
EVENTID,
VOLUNTEERTYPEID,
QUANTITYNEEDED,
STARTDATETIME as TIME,
1 as ISSTARTTIME
from @STAFFRESOURCESUSED
union all
select
SUPEREVENTID,
ITINERARYID,
ITINERARYITEMID,
EVENTID,
VOLUNTEERTYPEID,
QUANTITYNEEDED,
ENDDATETIME as TIME,
0 as ISSTARTTIME
from @STAFFRESOURCESUSED
) as T
order by T.SUPEREVENTID, T.TIME, T.ISSTARTTIME
open CONFLICTS_CURSOR;
fetch next from CONFLICTS_CURSOR
into
@THISSUPEREVENTID,
@THISITINERARYID,
@THISITINERARYITEMID,
@THISEVENTID,
@THISVOLUNTEERTYPEID,
@THISQUANTITYNEEDED,
@THISTIME,
@THISISSTARTTIME;
while @@FETCH_STATUS = 0
begin
if @CURRENTEVENTID is null
set @CURRENTEVENTID = @THISSUPEREVENTID
-- Reset current event if we are switching events, this is because we are going through
-- multiple events on conflict checking, ordered by eventid
if @CURRENTEVENTID <> @THISSUPEREVENTID
begin
delete from @CURRENTUSEDSTAFFRESOURCES
set @CURRENTEVENTID = @THISEVENTID
end
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
with STAFFRESOURCETOTAL_CTE as
(
select
VOLUNTEERTYPEID,
sum(QUANTITYNEEDED) as QUANTITYNEEDED,
count(VOLUNTEERTYPEID) as STAFFRESOURCECOUNT
from
(
select
VOLUNTEERTYPEID,
QUANTITYNEEDED
from @CURRENTUSEDSTAFFRESOURCES
union all
select
VOLUNTEERTYPEID,
QUANTITYNEEDED
from @STAFFRESOURCESTABLE
) as T
group by T.VOLUNTEERTYPEID
)
insert into @CONFLICTS
(
EVENTID
)
select
@THISSUPEREVENTID
from @CURRENTUSEDSTAFFRESOURCES as STAFFRESOURCESUSED
inner join STAFFRESOURCETOTAL_CTE STAFFRESOURCETOTAL on
STAFFRESOURCETOTAL.VOLUNTEERTYPEID = STAFFRESOURCESUSED.VOLUNTEERTYPEID
inner join dbo.VOLUNTEERTYPE on
STAFFRESOURCESUSED.VOLUNTEERTYPEID = VOLUNTEERTYPE.ID
where
not exists
(
select 1 from @CONFLICTS
where
[@CONFLICTS].EVENTID = @THISSUPEREVENTID
) and
STAFFRESOURCETOTAL.QUANTITYNEEDED > VOLUNTEERTYPE.QUANTITY and
STAFFRESOURCETOTAL.STAFFRESOURCECOUNT > 1
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
@THISSUPEREVENTID,
@THISITINERARYID,
@THISITINERARYITEMID,
@THISEVENTID,
@THISVOLUNTEERTYPEID,
@THISQUANTITYNEEDED,
@THISTIME,
@THISISSTARTTIME;
end
close CONFLICTS_CURSOR;
deallocate CONFLICTS_CURSOR;
return;
end