Calculates Rostered rate types based on work segment



/***********************************************************************************
Calculates rostered rate types based on work segment
This does not calculate rates. It's purely for breaking down the roster record.



SELECT * FROM [dbo].[GetWorkSegments] ('B0271037793', 'grp-act-cen')

SELECT r.*
FROM nbc.Roster r
WHERE DATEPART(hour, Start) < 8 AND DATEPART(hour, [End]) > 10

***********************************************************************************/

CREATE FUNCTION [dbo].[GetWorkSegments]
(
    @WorkSegmentId VARCHAR(100)
, @RosteredService VARCHAR(50)
)
RETURNS @Totals TABLE
(
RosteredServiceID VARCHAR(100)
  , RosteredService VARCHAR(50)
  , ShiftId INT
  , RateDayType VARCHAR(20)
  , WeekdayId INT
  , ShortDay CHAR(3)
  , [Weekday] VARCHAR(12)
  , ShiftDateKey INT
  , ShiftStart DATETIME2
  , ShiftEnd DATETIME2
  , MinutesInShift MONEY -- so we can multiply it by a rate
  , MinutesInSegment MONEY -- so we can multiply it by a rate
)
AS
BEGIN
DECLARE @StartDate DATE = (SELECT MIN([start]) FROM nbc.Roster WHERE RosteredServiceId = @WorkSegmentId AND RosteredService = @RosteredService);
DECLARE @EndDate DATE = (SELECT MIN([End]) FROM nbc.Roster WHERE RosteredServiceId = @WorkSegmentId AND RosteredService = @RosteredService);
--DECLARE @EndDate DATE = DATEADD(DAY,1,GETDATE());

DECLARE @Dates TABLE
    (
         ThisDate DATETIME2 PRIMARY KEY
        ,ThisWeekDay VARCHAR(25)
        ,UNIQUE(ThisWeekDay,ThisDate)
    );

WITH Dates_CTE AS
(
    SELECT @StartDate AS ThisDate
            , DATENAME(DW,@StartDate) AS ThisWeekDay
    UNION ALL
    SELECT NextDate, DATENAME(DW,NextDate)
    FROM Dates_CTE
CROSS APPLY (VALUES(DATEADD(DAY,1,ThisDate))) NextDates(NextDate)
    WHERE NextDate <= @EndDate
)
INSERT INTO @Dates
SELECT ThisDate,ThisWeekDay FROM Dates_CTE OPTION (MAXRECURSION 0);


DECLARE @ShiftStartDates TABLE
(
StartDate DATETIME2
  , ShiftId INT
   ,WeekdayId INT
  , DayCode CHAR(3)
  , UNIQUE(StartDate)
);

INSERT INTO @ShiftStartDates
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE,'00:00',S.startTime),D.ThisDate) AS startDate
      , S.ID AS ShiftId
      , W.ID AS WeekdayId
  , W.code as DayCode
FROM Shifts S
JOIN Shifts_Weekdays SW ON S.ID = SW.shiftID
JOIN Weekdays W ON SW.weekdayId = W.Id
JOIN @Dates D ON W.weekday = D.ThisWeekDay


DECLARE @ShiftDates TABLE
(
StartDate DATETIME2
  , EndDate DATETIME2
  , ShiftId INT
  , WeekdayId INT
  , UNIQUE(StartDate)
);

INSERT INTO @ShiftDates
SELECT StartDate
      , (SELECT TOP 1 StartDate FROM @ShiftStartDates WHERE StartDate > S.StartDate) AS EndDate
      , ShiftId
      , WeekdayId
FROM @ShiftStartDates S;

--Get results
INSERT INTO @Totals
SELECT RosteredServiceId
  , RosteredService
      , ShiftId
      , RateDayType
      , WeekdayId
      , ShortDay
      , [Weekday]
      , ShiftDateKey
      , ShiftStart
      , ShiftEnd
      , MinutesInShift
      , MinutesInSegment
FROM
(
SELECT r.RosteredServiceId
  , r.RosteredService
  , SD.ShiftId
  , CASE
WHEN wd.code = 'SAT' THEN 'SAT'
WHEN wd.code = 'SUN' THEN 'SUN'
WHEN h.Holiday IS NOT NULL THEN 'HOLIDAY'
ELSE sh.shift
END AS RateDayType
  , SD.WeekdayId
  , wd.code ShortDay
  , wd.weekday
  , CASE
                WHEN r.[Start] >= SD.StartDate AND r.[End] >= SD.EndDate THEN FORMAT(r.[Start], 'yyyyMMdd') 
                WHEN r.[Start] >= SD.StartDate AND r.[End] <= SD.EndDate THEN FORMAT(r.[Start], 'yyyyMMdd') 
                WHEN r.[Start] <= SD.StartDate AND r.[End] >= SD.EndDate THEN FORMAT(SD.startDate, 'yyyyMMdd') 
                WHEN r.[Start] <= SD.StartDate AND r.[End] <= SD.EndDate THEN FORMAT(SD.startDate, 'yyyyMMdd') 
            END AS ShiftDateKey
  , CASE
                WHEN r.[Start] >= SD.StartDate AND r.[End] >= SD.EndDate THEN r.[Start]
                WHEN r.[Start] >= SD.StartDate AND r.[End] <= SD.EndDate THEN r.[Start]
                WHEN r.[Start] <= SD.StartDate AND r.[End] >= SD.EndDate THEN SD.startDate
                WHEN r.[Start] <= SD.StartDate AND r.[End] <= SD.EndDate THEN SD.startDate
            END AS ShiftStart
  , CASE
                WHEN r.[Start] >= SD.StartDate AND r.[End] >= SD.EndDate THEN SD.endDate
                WHEN r.[Start] >= SD.StartDate AND r.[End] <= SD.EndDate THEN r.[End]
                WHEN r.[Start] <= SD.StartDate AND r.[End] >= SD.EndDate THEN SD.endDate
                WHEN r.[Start] <= SD.StartDate AND r.[End] <= SD.EndDate THEN r.[End]
            END AS ShiftEnd
  , CASE
                WHEN r.[Start] >= SD.StartDate AND r.[End] >= SD.EndDate THEN DATEDIFF(MINUTE,r.[Start],SD.endDate)
                WHEN r.[Start] >= SD.StartDate AND r.[End] <= SD.EndDate THEN DATEDIFF(MINUTE,r.[Start],r.[End])
                WHEN r.[Start] <= SD.StartDate AND r.[End] >= SD.EndDate THEN DATEDIFF(MINUTE,SD.startDate,SD.endDate)
                WHEN r.[Start] <= SD.StartDate AND r.[End] <= SD.EndDate THEN DATEDIFF(MINUTE,SD.startDate,r.[End])
            END AS MinutesInShift
  , DATEDIFF(MINUTE,r.[Start],r.[End]) AS MinutesInSegment
FROM [nbc].[Roster] r
INNER JOIN @ShiftDates SD ON r.[End] > SD.StartDate AND r.[Start] < SD.EndDate
INNER JOIN [nbc].[ServiceCentre] sc ON sc.ServiceCentre = r.ServiceCentre
INNER JOIN [dbo].[Weekdays] wd ON wd.ID = SD.WeekdayId
INNER JOIN [dbo].[Shifts] sh ON sh.ID = sd.ShiftId
LEFT JOIN [nbc].[RegionalHoliday] h ON FORMAT(SD.startDate, 'yyyyMMdd') = h.[DimDate_DateKey]
   AND h.[ServiceCentre_ScId] = sc.ScId
WHERE r.RosteredServiceId = @WorkSegmentId AND r.RosteredService = @RosteredService
    ) PayIntervals

RETURN;
END

GO


Comments

Popular posts from this blog

Request failed with HTTP status 503 Server Error

Removing and Manipulating Time portion from DateTime in SQLServer

Calculating Age of the person in T-SQL