USE [AdventureWorks2014]
GO
/****** Object:  Trigger [dbo].[TRIG_ZamykanieCen]    Script Date: 13.04.2019 19:06:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[TRIG_ZamykanieCen] 
   ON  [dbo].[aProductCostHistory] 
   INSTEAD OF INSERT
AS 
BEGIN
	--Deklaracja zmiennych
	DECLARE @ProductID        INT;
	DECLARE @StartDate        DATETIME;
	DECLARE @EndDate          DATETIME;
	DECLARE @StandardCost     MONEY;
	DECLARE @ModifiedDate     DATETIME;
	DECLARE @OldEndDate       DATETIME;
	DECLARE @OldStandardCost  MONEY;

	--Pobranie danych ze wstawianego rekordu
	SELECT
		@ProductID    = ProductID,
		@StartDate    = StartDate,
		@EndDate      = EndDate,
		@StandardCost = StandardCost
	FROM
		inserted;

	--Sprawdzenie i ustawienie @StartDate
	IF (@StartDate IS NULL) BEGIN
		--SET @StartDate = CONVERT(date, GETDATE());
		SET @StartDate = GETDATE();
		PRINT 'INFO:  Data początkowa była pusta i zostanie ustawiona na dzisiejszą.';
	END
	ELSE IF (@StartDate < GETDATE()) BEGIN
		PRINT 'INFO:  Nie wolno zmieniać cenników w przeszłości!';
		PRINT 'INFO:  Data początkowa zostanie zmieniona na dzisiejszą.';
		--SET @StartDate = CONVERT(date, GETDATE());
		SET @StartDate = GETDATE();
	END
	PRINT 'DEBUG: StartDate    = ' + CAST(@StartDate AS varchar(20));

	--Sprawdzenie i weryfikacja @EndDate
	IF (@EndDate IS NULL) BEGIN
		PRINT 'INFO:  Dodawany cennik będzie obowiązywał bezterminowo.';
	END
	ELSE IF (@EndDate < @StartDate) BEGIN
		THROW 50001, 'BŁĄD:  Data końcowa musi być większa od początkowej!', 1;
	END
	PRINT 'DEBUG: EndDate      = ' + CAST(@EndDate AS varchar(20));

	--Sprawdzenie i weryfikacja @StandardCost
	IF (@StandardCost IS NULL) BEGIN
		THROW 50002, 'BŁĄD:  Nie określono ceny!', 2;
	END
	PRINT 'DEBUG: StandardCost = ' + CAST(@StandardCost AS varchar(20));

	--Ustawienie daty modyfikacji @ModifiedDate
	SET @ModifiedDate = GETDATE();
	PRINT 'DEBUG: ModifiedDate = ' + CAST(@ModifiedDate AS varchar(20));

	--Usunięcie cen, które nigdy nie wejdą w życie, tj. wewnątrz okresu dodawanej oferty
	PRINT 'DEBUG: Usuwanie wpisów pomiędzy datami StartDate i EndDate.';
	DELETE FROM [dbo].[aProductCostHistory]
	WHERE
		ProductID  = @ProductID AND
		StartDate >= @StartDate AND
		EndDate   <= @EndDate;

	--Sprawdzenie oferty obowiązującej wcześniej (do skrócenia)
	PRINT 'DEBUG: Sprawdzanie poprzedniej oferty do skrócenia.'
	SELECT TOP (1)
		@OldEndDate      = EndDate,
		@OldStandardCost = StandardCost
	FROM [dbo].[aProductCostHistory]
	WHERE
		ProductID = @ProductID  AND
		StartDate < @StartDate
	ORDER BY StartDate DESC;
	PRINT 'DEBUG: OldEndDate      = ' + cast(@OldEndDate      as varchar(20))
	PRINT 'DEBUG: OldStandardCost = ' + cast(@OldStandardCost as varchar(20))

	--Skrócenie oferty obowiązującej wcześniej
	PRINT 'INFO:  Skracanie obowiązywania poprzedniej oferty.';
	UPDATE [dbo].[aProductCostHistory]
	SET EndDate = DATEADD(day, -1, @StartDate),
		ModifiedDate = GETDATE()
	WHERE
		ProductID    = @ProductID  AND
		EndDate      = @OldEndDate AND
		StandardCost = @OldStandardCost;

	IF (@OldEndDate > @EndDate) BEGIN
		--"Przywrócenie" oferty jeżeli obowiązywać dłużej niż nowo wprowadzana
		PRINT 'INFO:  Dodawanie rekordu z kontynuacją poprzedniej oferty.';
		INSERT INTO [dbo].[aProductCostHistory]
			(ProductID, StartDate, EndDate, StandardCost, ModifiedDate)
		VALUES (
			@ProductID,
			DATEADD(day, +1, @EndDate),
			@OldEndDate,
			@OldStandardCost,
			GETDATE()
		);
	END ELSE IF (@EndDate IS NOT NULL) BEGIN
		--Aktualizacja daty rozpoczęcia ofert przyszłych
		PRINT 'INFO:  Skrócenie oferty, która zaczynała się w nadpisywanym okresie.';
		UPDATE [dbo].[aProductCostHistory]
		SET StartDate = DATEADD(day, +1, @EndDate),
			ModifiedDate = GETDATE()
		WHERE
			ProductID  = @ProductID AND
			StartDate BETWEEN @StartDate AND @EndDate;
	END ELSE BEGIN
		--Usunięcie ofert, które były zaplanowane na przyszłość
		PRINT 'INFO:  Wstawiana oferta nie ma daty obowiązywania.';
		PRINT 'INFO:  Usuwanie poprzednich ofert dla dat nowszych niż StartDate.';
		DELETE FROM [dbo].[aProductCostHistory]
		WHERE
			ProductID  = @ProductID AND
			StartDate >= @StartDate;
	END

	--Dodanie rekordu, który wywołał całe zamieszanie
	PRINT 'INFO:  Dodanie rekordu oferty w wersji ostatecznej.';
	INSERT INTO [dbo].[aProductCostHistory]
		(ProductID, StartDate, EndDate, StandardCost, ModifiedDate)
	VALUES (
		@ProductID,
		@StartDate,
		@EndDate,
		@StandardCost,
		GETDATE()
	);

	PRINT 'Trigger się uruchomił :-)';
	PRINT 'ProductID       = ' + cast(@ProductID as varchar(20));
	PRINT '   StartDate    = ' + cast(@StartDate as varchar(20));
	PRINT '   StartDate-1  = ' + cast(DATEADD(day, -1, @StartDate) as varchar(20));
	PRINT '   EndDate      = ' + cast(@EndDate as varchar(20));
	PRINT '   EndDate+1    = ' + cast(DATEADD(day, +1, @EndDate) as varchar(20));
	PRINT '   StandardCost = ' + cast(@StandardCost as varchar(20));
	PRINT 'OldEndDate      = ' + cast(@OldEndDate as varchar(20));
	PRINT 'OldStandardCost = ' + cast(@OldStandardCost as varchar(20));

	THROW 50003, 'BŁĄD:  (albo nie...) Sprawdźmy, czy zmiany się wycofały!', 3;
END
