SET NOCOUNT ON; USE HistorySchemes; GO -- ============================================================================ -- ============================================================================ -- AccountDiff -- ============================================================================ -- ============================================================================ IF OBJECT_ID('AccountDiffHistory') IS NOT NULL DROP TABLE dbo.AccountDiffHistory; GO IF OBJECT_ID('AccountDiff') IS NOT NULL DROP TABLE dbo.AccountDiff; GO -- ========== Table: AccountDiff -- Store one history record for each change to the Account record (including creation). IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'AccountDiff' AND TABLE_SCHEMA = N'dbo' AND TABLE_TYPE = N'BASE TABLE') BEGIN PRINT N'Create table AccountDiff'; CREATE TABLE dbo.AccountDiff ( AccountDiffID int NOT NULL IDENTITY, PrimaryCardHolderID int NOT NULL, Address1 varchar(40) NOT NULL, Address2 varchar(40) NOT NULL, City varchar(40) NOT NULL, [State] char(2) NOT NULL, ZipCode varchar(10) NOT NULL, StatusCd tinyint NOT NULL CONSTRAINT AccountDiff_StatusCd_DF DEFAULT 1, -- See code-to-string conversion in AccountDiffView CONSTRAINT AccountDiff_PK PRIMARY KEY CLUSTERED (AccountDiffID) ); END; GO --DENY DELETE, INSERT, REFERENCES, UPDATE ON OBJECT::dbo.AccountDiff TO SqlCreditAppSqlRole; --GO -- ========== Table: AccountDiffHistory IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'AccountDiffHistory' AND TABLE_SCHEMA = N'dbo' AND TABLE_TYPE = N'BASE TABLE') BEGIN PRINT N'Create table AccountDiffHistory'; CREATE TABLE dbo.AccountDiffHistory ( AccountDiffHistoryID int NOT NULL IDENTITY, AccountDiffID int NOT NULL, UpdateUserID int NOT NULL, -- The user making the INSERT/UPDATE/DELETE call HistoryDate datetime NOT NULL CONSTRAINT AccountDiffHistory_HistoryDate_DF DEFAULT GETUTCDATE(), PrimaryCardHolderID int NOT NULL, Address1 varchar(40) NOT NULL, Address2 varchar(40) NOT NULL, City varchar(40) NOT NULL, [State] char(2) NOT NULL, ZipCode varchar(10) NOT NULL, StatusCd tinyint NOT NULL CONSTRAINT AccountDiffHistory_StatusCd_DF DEFAULT 1, CONSTRAINT AccountDiffHistory_PK PRIMARY KEY CLUSTERED (AccountDiffHistoryID), CONSTRAINT AccountDiffHistory_AccountDiffID_FK FOREIGN KEY (AccountDiffID) REFERENCES dbo.AccountDiff (AccountDiffID) ); END; GO --DENY DELETE, INSERT, REFERENCES, UPDATE ON OBJECT::dbo.AccountDiffHistory TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountDiffCreate'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountDiffCreate' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountDiffCreate; GO CREATE PROCEDURE dbo.AccountDiffCreate ( @AccountDiffID int OUTPUT, @UpdateUserID int, @Address1 varchar(40), @Address2 varchar(40), @City varchar(40), @State char(2), @ZipCode varchar(10), @TestMode int = NULL -- Use values between 11 and 20 ) AS -- Create a new AccountDiff record BEGIN SET NOCOUNT ON; DECLARE @error int; DECLARE @list nvarchar(255); DECLARE @rowcount int; DECLARE @spName sysname; SELECT @spName = Object_Name(@@ProcID); -- This must be called from within an explicit transaction IF @@TRANCOUNT = 0 BEGIN RAISERROR(999007, 10, 1, @spName, N'') WITH SETERROR; RETURN(@@error); END; INSERT INTO dbo.AccountDiff ( -- AccountDiffID PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode -- StatusCd ) VALUES ( @UpdateUserID, -- PrimaryCardHolderID @Address1, @Address2, @City, @State, @ZipCode ); SELECT @error = @@error, @rowcount = @@rowcount, @AccountDiffID = SCOPE_IDENTITY(); IF @error <> 0 OR @rowcount <> 1 OR @TestMode IN (11, 12) BEGIN -- Let the calling code do the ROLLBACK EXEC dbo.TagValueList @list OUTPUT, N'@Address1', @Address1, N'@Address2', @Address2, N'@City', @City, N'@State', @State, N'@ZipCode', @ZipCode; IF @error <> 0 OR @TestMode = 11 BEGIN RAISERROR(999001, 10, 1, @spName, @error, N'AccountDiff', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 12 BEGIN RAISERROR(999002, 10, 1, @spName, N'AccountDiff', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; -- History Record INSERT INTO dbo.AccountDiffHistory ( -- AccountDiffHistoryID AccountDiffID, UpdateUserID, -- HistoryDate PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode -- StatusCd ) VALUES ( @AccountDiffID, @UpdateUserID, -- UpdateUserID @UpdateUserID, -- PrimaryCardHolderID @Address1, @Address2, @City, @State, @ZipCode ); SELECT @error = @@error, @rowcount = @@rowcount; IF @error <> 0 OR @rowcount <> 1 OR @TestMode IN (11, 12) BEGIN -- Let the calling code do the ROLLBACK EXEC dbo.TagValueList @list OUTPUT, N'@AccountDiffID', @AccountDiffID, N'@Address1', @Address1, N'@Address2', @Address2, N'@City', @City, N'@State', @State, N'@ZipCode', @ZipCode; IF @error <> 0 OR @TestMode = 11 BEGIN RAISERROR(999001, 10, 1, @spName, @error, N'AccountDiffHistory', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 12 BEGIN RAISERROR(999002, 10, 1, @spName, N'AccountDiffHistory', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountDiffCreate TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountDiffReadByID'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountDiffReadByID' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountDiffReadByID; GO CREATE PROCEDURE dbo.AccountDiffReadByID ( @AccountDiffID int, @ExcludeDeleted bit = 1 -- By default, do not return deleted records ) AS -- Read a single AccountDiff record by AccountDiffID BEGIN SET NOCOUNT ON; IF @ExcludeDeleted = 1 BEGIN SELECT AccountDiffID, PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode, StatusCd FROM dbo.AccountDiff WHERE AccountDiffID = @AccountDiffID AND StatusCd <> 4; -- 4 = 'DELETED' END; ELSE BEGIN SELECT AccountDiffID, PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode, StatusCd FROM dbo.AccountDiff WHERE AccountDiffID = @AccountDiffID; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountDiffReadByID TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountDiffUpdate'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountDiffUpdate' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountDiffUpdate; GO CREATE PROCEDURE dbo.AccountDiffUpdate ( @AccountDiffID int, @UpdateUserID int, @PrimaryCardHolderID int, @Address1 varchar(40), @Address2 varchar(40), @City varchar(40), @State char(2), @ZipCode varchar(10), @StatusCd tinyint, @TestMode int = NULL ) AS -- Update an AccountDiff record -- Do not allow updates of deleted records BEGIN SET NOCOUNT ON; DECLARE @error int; DECLARE @list nvarchar(255); DECLARE @localTran bit; DECLARE @rowcount int; DECLARE @spName sysname; SELECT @spName = Object_Name(@@ProcID); SELECT @localTran = 0; IF @@TRANCOUNT = 0 BEGIN BEGIN TRAN; SELECT @localTran = 1; END; UPDATE dbo.AccountDiff SET PrimaryCardHolderID = @PrimaryCardHolderID, Address1 = @Address1, Address2 = @Address2, City = @City, [State] = @State, ZipCode = @ZipCode, StatusCd = @StatusCd WHERE AccountDiffID = @AccountDiffID AND StatusCd <> 4; -- 4 = 'DELETED' SELECT @error = @@error, @rowcount = @@rowcount; IF @error <> 0 OR @rowcount <> 1 OR @TestMode IN (1, 2) BEGIN IF @localTran = 1 BEGIN ROLLBACK TRAN; END; EXEC dbo.TagValueList @list OUTPUT, N'@AccountDiffID', @AccountDiffID, N'@PrimaryCardHolderID', @PrimaryCardHolderID, N'@Address1', @Address1, N'@Address2', @Address2, N'@City', @City, N'@State', @State, N'@ZipCode', @ZipCode, N'@StatusCd', @StatusCd; IF @error <> 0 OR @TestMode = 1 BEGIN RAISERROR(999003, 10, 1, @spName, @error, N'AccountDiff', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 2 BEGIN -- If record is deleted, RAISERROR and RETURN IF EXISTS ( SELECT 1 FROM dbo.AccountDiff WHERE AccountDiffID = @AccountDiffID AND StatusCd = 4 -- 4 = 'DELETED' ) BEGIN EXEC dbo.TagValueList @list OUTPUT, N'@AccountDiffID', @AccountDiffID; RAISERROR(999500, 10, 1, @list) WITH SETERROR; RETURN(@@error); END; -- Else, return generic error RAISERROR(999004, 10, 1, @spName, N'AccountDiff', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; -- History Record INSERT INTO dbo.AccountDiffHistory ( -- AccountDiffHistoryID AccountDiffID, UpdateUserID, -- HistoryDate PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode, StatusCd ) VALUES ( @AccountDiffID, @UpdateUserID, @PrimaryCardHolderID, @Address1, @Address2, @City, @State, @ZipCode, @StatusCd ); SELECT @error = @@error, @rowcount = @@rowcount; IF @error <> 0 OR @rowcount <> 1 OR @TestMode IN (3, 4) BEGIN IF @localTran = 1 BEGIN ROLLBACK TRAN; END; EXEC dbo.TagValueList @list OUTPUT, N'AccountDiffID', @AccountDiffID, N'@UpdateUserID', @UpdateUserID, N'@PrimaryCardHolderID', @PrimaryCardHolderID, N'@Address1', @Address1, N'@Address2', @Address2, N'@City', @City, N'@State', @State, N'@ZipCode', @ZipCode, N'@StatusCd', @StatusCd; IF @error <> 0 OR @TestMode = 3 BEGIN RAISERROR(999001, 10, 1, @spName, @error, N'AccountDiffHistory', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 4 BEGIN RAISERROR(999002, 10, 1, @spName, N'AccountDiffHistory', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; IF @localTran = 1 BEGIN COMMIT TRAN; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountDiffUpdate TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountDiffUpdateStatusCd'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountDiffUpdateStatusCd' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountDiffUpdateStatusCd; GO CREATE PROCEDURE dbo.AccountDiffUpdateStatusCd ( @AccountDiffID int, @UpdateUserID int, @StatusCd tinyint, @TestMode int = NULL ) AS -- Update only the StatusCd of an AccountDiff record BEGIN SET NOCOUNT ON; DECLARE @error int; DECLARE @list nvarchar(255); DECLARE @localTran bit; DECLARE @rowcount int; DECLARE @spName sysname; SELECT @spName = Object_Name(@@ProcID); SELECT @localTran = 0; IF @@TRANCOUNT = 0 BEGIN BEGIN TRAN; SELECT @localTran = 1; END; -- Inserting the history record first makes the coding much easier, -- and it's all in a transaction, so consistency is guaranteed. -- History Record INSERT INTO dbo.AccountDiffHistory ( -- AccountDiffHistoryID AccountDiffID, UpdateUserID, -- HistoryDate PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode, StatusCd ) SELECT AccountDiffID, @UpdateUserID, PrimaryCardHolderID, Address1, Address2, City, State, ZipCode, @StatusCd -- New status FROM dbo.AccountDiff WHERE AccountDiffID = @AccountDiffID AND StatusCd <> 4; -- 4 = 'DELETED' SELECT @error = @@error, @rowcount = @@rowcount; IF @error <> 0 OR @rowcount <> 1 OR @TestMode IN (1, 2) BEGIN IF @localTran = 1 BEGIN ROLLBACK TRAN; END; EXEC dbo.TagValueList @list OUTPUT, N'AccountDiffID', @AccountDiffID, N'@StatusCd', @StatusCd; IF @error <> 0 OR @TestMode = 1 BEGIN RAISERROR(999001, 10, 1, @spName, @error, N'AccountDiffHistory', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 2 BEGIN RAISERROR(999002, 10, 1, @spName, N'AccountDiffHistory', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; -- Update UPDATE dbo.AccountDiff SET StatusCd = @StatusCd WHERE AccountDiffID = @AccountDiffID; -- We already know the record is not deleted SELECT @error = @@error, @rowcount = @@rowcount; IF @error <> 0 OR @rowcount <> 1 OR @TestMode IN (3, 4) BEGIN IF @localTran = 1 BEGIN ROLLBACK TRAN; END; EXEC dbo.TagValueList @list OUTPUT, N'AccountDiffID', @AccountDiffID, N'StatusCd', @StatusCd; IF @error <> 0 OR @TestMode = 3 BEGIN RAISERROR(999003, 10, 1, @spName, @error, N'AccountDiff', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 4 BEGIN RAISERROR(999004, 10, 1, @spName, N'AccountDiff', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; IF @localTran = 1 BEGIN COMMIT TRAN; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountDiffUpdateStatusCd TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountDiffDelete'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountDiffDelete' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountDiffDelete; GO CREATE PROCEDURE dbo.AccountDiffDelete ( @AccountDiffID int, @UpdateUserID int, @TestMode int = NULL ) AS -- Delete an AccountDiff record -- Deleting a record involves just updating its status, so call AccountDiffUpdateStatusCd BEGIN SET NOCOUNT ON; DECLARE @returnValue int; SELECT @returnValue = NULL; EXEC @returnValue = dbo.AccountDiffUpdateStatusCd @AccountDiffID = @AccountDiffID, @UpdateUserID = @UpdateUserID, @StatusCd = 4, -- 4 = DELETED @TestMode = @TestMode; IF @returnValue IS NULL OR @returnValue <> 0 BEGIN RETURN ISNULL(@returnValue, -1); END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountDiffDelete TO SqlCreditAppSqlRole; --GO PRINT N'<< DONE >>' GO -- ============================================================================ -- TESTS -- ============================================================================ -- These are quick validation tests, not complete unit tests DECLARE @acctID1 int; DECLARE @rtn int; BEGIN TRAN; SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffCreate @AccountDiffID = @acctID1 OUTPUT, @UpdateUserID = 1000, @Address1 = 'Address1', @Address2 = 'Address2', @City = 'City', @State = 'OR', @ZipCode = '97124'; COMMIT TRAN; SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffReadByID @AccountDiffID = @acctID1; SELECT * FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffUpdateStatusCd @AccountDiffID = @acctID1, @UpdateUserID = 99, @StatusCd = 3; -- 3 = 'LOCKED' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffReadByID @AccountDiffID = @acctID1; SELECT * FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffUpdateStatusCd @AccountDiffID = @acctID1, @UpdateUserID = 99, @StatusCd = 1; -- 1 = 'ACTIVE' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffReadByID @AccountDiffID = @acctID1; SELECT * FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffUpdate @AccountDiffID = @acctID1, @UpdateUserID = 1001, @PrimaryCardholderID = 1000, @Address1 = 'Address1x', @Address2 = 'Address2x', @City = 'Cityx', @State = 'WA', @ZipCode = '97125', @StatusCd = 1; -- 1 = 'ACTIVE' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffReadByID @AccountDiffID = @acctID1; SELECT * FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID -- Call update again, changing only the PrimaryCardholdID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffUpdate @AccountDiffID = @acctID1, @PrimaryCardholderID = 1001, @UpdateUserID = 1000, @Address1 = 'Address1x', @Address2 = 'Address2x', @City = 'Cityx', @State = 'WA', @ZipCode = '97125', @StatusCd = 1; -- 1 = 'ACTIVE' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffReadByID @AccountDiffID = @acctID1; SELECT * FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffUpdateStatusCd @AccountDiffID = @acctID1, @UpdateUserID = 99, @StatusCd = 2; -- 2 = 'INACTIVE' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffReadByID @AccountDiffID = @acctID1; SELECT * FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffDelete @AccountDiffID = @acctID1, @UpdateUserID = 1; SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffReadByID @AccountDiffID = @acctID1; SELECT * FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID PRINT 'Expect failure updating deleted record' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountDiffUpdate @AccountDiffID = @acctID1, @UpdateUserID = 1001, @PrimaryCardholderID = 1000, @Address1 = 'Address1x', @Address2 = 'Address2x', @City = 'Cityx', @State = 'WA', @ZipCode = '97125', @StatusCd = 2; -- 2 = 'INACTIVE' SELECT UpdateUserID, PrimaryCardholderID, StatusCd --, HistoryDate FROM dbo.AccountDiffHistory WHERE AccountDiffID = @acctID1 ORDER BY AccountDiffHistoryID