
IF EXISTS (SELECT 1 FROM [dbo].[sysobjects] WHERE id = object_id(N'[dbo].[fn_AdjustDateForItemProcessTime]') AND xtype IN (N'FN', N'IF', N'TF'))
	DROP FUNCTION [dbo].[fn_AdjustDateForItemProcessTime]
GO

CREATE FUNCTION [dbo].[fn_AdjustDateForItemProcessTime]
(	
	@entityId INT
	, @date DATETIME
	, @processingHours INT
	, @closedDays UDT_ClosedDates READONLY
)
RETURNS DATETIME

AS
BEGIN

	DECLARE
		@isClosedDay BIT = 0
		, @nextDate DATETIME = @date
		, @remainingHours INT = @processingHours
		, @closedDayCount INT = 0

	-- If processing time is over 24 hours, first check if the first days are closed.
	WHILE (@remainingHours > 24)
	BEGIN
		SET @nextDate = DATEADD(HOUR, 24, @nextDate)
		SET @closedDayCount = @closedDayCount + CASE WHEN EXISTS (SELECT 1 FROM @closedDays WHERE ClosedDate = @nextDate) THEN 1 ELSE 0 END
		SET @remainingHours = @remainingHours - 24
	END

	SET @nextDate = DATEADD(HOUR, @remainingHours, @nextDate)

	-- Check if the current/ending date is closed.
	SET @isClosedDay = CASE WHEN EXISTS (SELECT 1 FROM @closedDays WHERE ClosedDate = @nextDate) THEN 1 ELSE 0 END

	WHILE (@isClosedDay = 1) -- Shift last day to the next day if it's a closed day.
	BEGIN	
		SET @closedDayCount = @closedDayCount + 1
		SET @nextDate = DATEADD(DAY, 1, @nextDate)
		SET @isClosedDay = CASE WHEN EXISTS (SELECT 1 FROM @closedDays WHERE ClosedDate = @nextDate) THEN 1 ELSE 0 END
	END

	RETURN DATEADD(HOUR, (@closedDayCount * 24) + @processingHours, @date)
END

GO
