SET NOCOUNT ON; USE HistorySchemes; GO -- ============================================================================ -- ============================================================================ -- AccountMin -- ============================================================================ -- ============================================================================ IF OBJECT_ID('AccountMinHistory') IS NOT NULL DROP TABLE dbo.AccountMinHistory; GO IF OBJECT_ID('AccountMin') IS NOT NULL DROP TABLE dbo.AccountMin; GO -- ========== Table: AccountMin -- Store one history record for each change to the Account record (including creation). -- This table is an exact copy of AccountDiff. IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'AccountMin' AND TABLE_SCHEMA = N'dbo' AND TABLE_TYPE = N'BASE TABLE') BEGIN PRINT N'Create table AccountMin'; CREATE TABLE dbo.AccountMin ( AccountMinID 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 AccountMin_StatusCd_DF DEFAULT 1, -- See code-to-string conversion in AccountMinView CONSTRAINT AccountMin_PK PRIMARY KEY CLUSTERED (AccountMinID) ); END; GO --DENY DELETE, INSERT, REFERENCES, UPDATE ON OBJECT::dbo.AccountMin TO SqlCreditAppSqlRole; --GO -- ========== Table: AccountMinHistory -- This table is different from AccountDiffHistory in that most columns are nullable. -- Store only the columns that have changed. IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'AccountMinHistory' AND TABLE_SCHEMA = N'dbo' AND TABLE_TYPE = N'BASE TABLE') BEGIN PRINT N'Create table AccountMinHistory'; CREATE TABLE dbo.AccountMinHistory ( AccountMinHistoryID int NOT NULL IDENTITY, AccountMinID int NOT NULL, UpdateUserID int NOT NULL, -- The user making the INSERT/UPDATE/DELETE call HistoryDate datetime NOT NULL CONSTRAINT AccountMinHistory_HistoryDate_DF DEFAULT GETUTCDATE(), PrimaryCardHolderID int NULL, Address1 varchar(40) NULL, Address2 varchar(40) NULL, City varchar(40) NULL, [State] char(2) NULL, ZipCode varchar(10) NULL, StatusCd tinyint NULL CONSTRAINT AccountMinHistory_StatusCd_DF DEFAULT 1, CONSTRAINT AccountMinHistory_PK PRIMARY KEY CLUSTERED (AccountMinHistoryID), CONSTRAINT AccountMinHistory_AccountMinID_FK FOREIGN KEY (AccountMinID) REFERENCES dbo.AccountMin (AccountMinID) ); END; GO --DENY DELETE, INSERT, REFERENCES, UPDATE ON OBJECT::dbo.AccountMinHistory TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountMinCreate'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountMinCreate' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountMinCreate; GO CREATE PROCEDURE dbo.AccountMinCreate ( @AccountMinID 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 AccountMin 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.AccountMin ( -- AccountMinID PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode -- StatusCd ) VALUES ( @UpdateUserID, -- PrimaryCardHolderID @Address1, @Address2, @City, @State, @ZipCode ); SELECT @error = @@error, @rowcount = @@rowcount, @AccountMinID = 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'AccountMin', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 12 BEGIN RAISERROR(999002, 10, 1, @spName, N'AccountMin', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; -- History Record INSERT INTO dbo.AccountMinHistory ( -- AccountMinHistoryID AccountMinID, UpdateUserID, -- HistoryDate PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode -- StatusCd ) VALUES ( @AccountMinID, @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'@AccountMinID', @AccountMinID, N'@UpdateUserID', @UpdateUserID, 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'AccountMinHistory', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 12 BEGIN RAISERROR(999002, 10, 1, @spName, N'AccountMinHistory', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountMinCreate TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountMinReadByID'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountMinReadByID' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountMinReadByID; GO CREATE PROCEDURE dbo.AccountMinReadByID ( @AccountMinID int, @ExcludeDeleted bit = 1 -- By default, do not return deleted records ) AS -- Read a single AccountMin record by AccountMinID BEGIN SET NOCOUNT ON; IF @ExcludeDeleted = 1 BEGIN SELECT AccountMinID, PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode, StatusCd FROM dbo.AccountMin WHERE AccountMinID = @AccountMinID AND StatusCd <> 4; -- 4 = 'DELETED' END; ELSE BEGIN SELECT AccountMinID, PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode, StatusCd FROM dbo.AccountMin WHERE AccountMinID = @AccountMinID; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountMinReadByID TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountMinUpdate'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountMinUpdate' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountMinUpdate; GO CREATE PROCEDURE dbo.AccountMinUpdate ( @AccountMinID int, @UpdateUserID int, @PrimaryCardHolderID int = NULL, @Address1 varchar(40) = NULL, @Address2 varchar(40) = NULL, @City varchar(40) = NULL, @State char(2) = NULL, @ZipCode varchar(10) = NULL, @StatusCd tinyint = NULL, @TestMode int = NULL ) AS -- Update an AccountMin record. -- Do not allow updates of deleted records. -- Pass only the values that are being updated. 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; -- History Record -- Write this record first so that the values in the base table have not changed. INSERT INTO dbo.AccountMinHistory ( -- AccountMinHistoryID AccountMinID, UpdateUserID, -- HistoryDate PrimaryCardHolderID, Address1, Address2, City, [State], ZipCode, StatusCd ) SELECT @AccountMinID, @UpdateUserID, CASE WHEN PrimaryCardHolderID = @PrimaryCardHolderID THEN NULL ELSE @PrimaryCardHolderID END, CASE WHEN Address1 = @Address1 THEN NULL ELSE @Address1 END, CASE WHEN Address2 = @Address2 THEN NULL ELSE @Address2 END, CASE WHEN City = @City THEN NULL ELSE @City END, CASE WHEN State = @State THEN NULL ELSE @State END, CASE WHEN ZipCode = @ZipCode THEN NULL ELSE @ZipCode END, CASE WHEN StatusCd = @StatusCd THEN NULL ELSE @StatusCd END FROM dbo.AccountMin WHERE AccountMinID = @AccountMinID 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'AccountMinID', @AccountMinID, 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 = 1 BEGIN RAISERROR(999001, 10, 1, @spName, @error, N'AccountMinHistory', @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.AccountMin WHERE AccountMinID = @AccountMinID AND StatusCd = 4 -- 4 = 'DELETED' ) BEGIN EXEC dbo.TagValueList @list OUTPUT, N'@AccountMinID', @AccountMinID; RAISERROR(999500, 10, 1, @list) WITH SETERROR; RETURN(@@error); END; -- Else, return generic error RAISERROR(999002, 10, 1, @spName, N'AccountMinHistory', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; UPDATE dbo.AccountMin SET PrimaryCardHolderID = @PrimaryCardHolderID, Address1 = @Address1, Address2 = @Address2, City = @City, [State] = @State, ZipCode = @ZipCode, StatusCd = @StatusCd WHERE AccountMinID = @AccountMinID; 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'@AccountMinID', @AccountMinID, 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(999003, 10, 1, @spName, @error, N'AccountMin', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 4 BEGIN RAISERROR(999004, 10, 1, @spName, N'AccountMin', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; IF @localTran = 1 BEGIN COMMIT TRAN; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountMinUpdate TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountMinUpdateStatusCd'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountMinUpdateStatusCd' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountMinUpdateStatusCd; GO CREATE PROCEDURE dbo.AccountMinUpdateStatusCd ( @AccountMinID int, @UpdateUserID int, @StatusCd tinyint, @TestMode int = NULL ) AS -- Update only the StatusCd of an AccountMin 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; -- Update UPDATE dbo.AccountMin SET StatusCd = @StatusCd WHERE AccountMinID = @AccountMinID 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'AccountMinID', @AccountMinID, N'StatusCd', @StatusCd; IF @error <> 0 OR @TestMode = 1 BEGIN RAISERROR(999003, 10, 1, @spName, @error, N'AccountMin', @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.AccountMin WHERE AccountMinID = @AccountMinID AND StatusCd = 4 -- 4 = 'DELETED' ) BEGIN EXEC dbo.TagValueList @list OUTPUT, N'@AccountMinID', @AccountMinID; RAISERROR(999500, 10, 1, @list) WITH SETERROR; RETURN(@@error); END; -- Else, return generic error RAISERROR(999004, 10, 1, @spName, N'AccountMin', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; -- History Record INSERT INTO dbo.AccountMinHistory ( -- AccountMinHistoryID AccountMinID, UpdateUserID, -- HistoryDate -- ... -- All the other nullable columns will receive NULLS StatusCd ) VALUES ( @AccountMinID, @UpdateUserID, @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'AccountMinID', @AccountMinID, N'@StatusCd', @StatusCd; IF @error <> 0 OR @TestMode = 3 BEGIN RAISERROR(999001, 10, 1, @spName, @error, N'AccountMinHistory', @list); RETURN(@error); END; ELSE IF @rowcount <> 1 OR @TestMode = 4 BEGIN RAISERROR(999002, 10, 1, @spName, N'AccountMinHistory', @rowcount, @list) WITH SETERROR; RETURN(@@error); END; END; IF @localTran = 1 BEGIN COMMIT TRAN; END; RETURN(0); END; GO --GRANT EXEC ON dbo.AccountMinUpdateStatusCd TO SqlCreditAppSqlRole; --GO -- ===================================================== PRINT N'AccountMinDelete'; -- ===================================================== IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'AccountMinDelete' AND ROUTINE_TYPE = N'PROCEDURE' AND ROUTINE_SCHEMA = N'dbo') DROP PROCEDURE dbo.AccountMinDelete; GO CREATE PROCEDURE dbo.AccountMinDelete ( @AccountMinID int, @UpdateUserID int, @TestMode int = NULL ) AS -- Delete an AccountMin record -- Deleting a record involves just updating its status, so call AccountMinUpdateStatusCd BEGIN SET NOCOUNT ON; DECLARE @returnValue int; SELECT @returnValue = NULL; EXEC @returnValue = dbo.AccountMinUpdateStatusCd @AccountMinID = @AccountMinID, @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.AccountMinDelete 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.AccountMinCreate @AccountMinID = @acctID1 OUTPUT, @UpdateUserID = 1000, @Address1 = 'Address1', @Address2 = 'Address2', @City = 'City', @State = 'OR', @ZipCode = '97124'; COMMIT TRAN; SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinReadByID @AccountMinID = @acctID1; SELECT * FROM dbo.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinUpdateStatusCd @AccountMinID = @acctID1, @UpdateUserID = 99, @StatusCd = 3; -- 3 = 'LOCKED' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinReadByID @AccountMinID = @acctID1; SELECT * FROM dbo.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinUpdateStatusCd @AccountMinID = @acctID1, @UpdateUserID = 99, @StatusCd = 1; -- 1 = 'ACTIVE' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinReadByID @AccountMinID = @acctID1; SELECT * FROM dbo.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinUpdate @AccountMinID = @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.AccountMinReadByID @AccountMinID = @acctID1; SELECT * FROM dbo.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID -- Call update again, changing only the PrimaryCardholdID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinUpdate @AccountMinID = @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.AccountMinReadByID @AccountMinID = @acctID1; SELECT * FROM dbo.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinUpdateStatusCd @AccountMinID = @acctID1, @UpdateUserID = 99, @StatusCd = 2; -- 2 = 'INACTIVE' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinReadByID @AccountMinID = @acctID1; SELECT * FROM dbo.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinDelete @AccountMinID = @acctID1, @UpdateUserID = 1; SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinReadByID @AccountMinID = @acctID1; SELECT * FROM dbo.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID PRINT 'Expect failure updating deleted record' SELECT @rtn = NULL; EXEC @rtn = dbo.AccountMinUpdate @AccountMinID = @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.AccountMinHistory WHERE AccountMinID = @acctID1 ORDER BY AccountMinHistoryID