Files
PowderCoatingLogix/apply-migration-safely.sql
T
2026-04-23 21:38:24 -04:00

195 lines
6.2 KiB
Transact-SQL

-- Safe Multi-Tenancy Migration Script
-- Run this instead of 'dotnet ef database update'
USE PowderCoatingDb;
GO
PRINT '=== Step 1: Create Companies Table ===';
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Companies')
BEGIN
CREATE TABLE Companies (
Id INT IDENTITY(1,1) PRIMARY KEY,
CompanyName NVARCHAR(MAX) NOT NULL,
CompanyCode NVARCHAR(450) NULL,
PrimaryContactName NVARCHAR(MAX) NOT NULL,
PrimaryContactEmail NVARCHAR(MAX) NOT NULL,
Phone NVARCHAR(MAX) NULL,
Address NVARCHAR(MAX) NULL,
City NVARCHAR(MAX) NULL,
State NVARCHAR(MAX) NULL,
ZipCode NVARCHAR(MAX) NULL,
IsActive BIT NOT NULL DEFAULT 1,
SubscriptionStartDate DATETIME2 NOT NULL,
SubscriptionEndDate DATETIME2 NULL,
SubscriptionPlan NVARCHAR(MAX) NULL,
TimeZone NVARCHAR(MAX) NULL,
LogoPath NVARCHAR(MAX) NULL,
Settings NVARCHAR(MAX) NULL,
CompanyId INT NOT NULL DEFAULT 0,
CreatedAt DATETIME2 NOT NULL,
UpdatedAt DATETIME2 NULL,
CreatedBy NVARCHAR(MAX) NULL,
UpdatedBy NVARCHAR(MAX) NULL,
IsDeleted BIT NOT NULL DEFAULT 0,
DeletedAt DATETIME2 NULL,
DeletedBy NVARCHAR(MAX) NULL
);
CREATE UNIQUE INDEX IX_Companies_CompanyCode ON Companies(CompanyCode) WHERE CompanyCode IS NOT NULL;
PRINT 'Companies table created';
END
GO
PRINT '=== Step 2: Insert Default Company ===';
IF NOT EXISTS (SELECT * FROM Companies WHERE Id = 1)
BEGIN
SET IDENTITY_INSERT Companies ON;
INSERT INTO Companies (
Id, CompanyName, CompanyCode, PrimaryContactName, PrimaryContactEmail,
Phone, Address, City, State, ZipCode,
IsActive, SubscriptionStartDate, SubscriptionPlan, TimeZone,
CompanyId, CreatedAt, IsDeleted
) VALUES (
1, 'Demo Company', 'DEMO', 'Admin User', 'admin@demo.com',
'(555) 123-4567', '123 Demo Street', 'Demo City', 'CA', '90210',
1, GETUTCDATE(), 'Enterprise', 'America/New_York',
1, GETUTCDATE(), 0
);
SET IDENTITY_INSERT Companies OFF;
PRINT 'Default company inserted';
END
GO
PRINT '=== Step 3: Add CompanyId Columns ===';
-- AspNetUsers
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('AspNetUsers') AND name = 'CompanyId')
BEGIN
ALTER TABLE AspNetUsers ADD CompanyId INT NOT NULL DEFAULT 1;
PRINT 'Added CompanyId to AspNetUsers';
END
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('AspNetUsers') AND name = 'CompanyRole')
BEGIN
ALTER TABLE AspNetUsers ADD CompanyRole NVARCHAR(MAX) NULL;
PRINT 'Added CompanyRole to AspNetUsers';
END
-- Other tables
DECLARE @sql NVARCHAR(MAX);
DECLARE @tableName NVARCHAR(128);
DECLARE cur CURSOR FOR
SELECT name FROM sys.tables
WHERE name IN ('Customers', 'Jobs', 'JobItems', 'Quotes', 'QuoteItems',
'InventoryItems', 'InventoryTransactions', 'Equipment',
'MaintenanceRecords', 'Suppliers', 'PricingTiers',
'JobPhotos', 'JobNotes', 'CustomerNotes', 'JobStatusHistory');
OPEN cur;
FETCH NEXT FROM cur INTO @tableName;
WHILE @@FETCH_STATUS = 0
BEGIN
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(@tableName) AND name = 'CompanyId')
BEGIN
SET @sql = N'ALTER TABLE ' + QUOTENAME(@tableName) + N' ADD CompanyId INT NOT NULL DEFAULT 1';
EXEC sp_executesql @sql;
PRINT 'Added CompanyId to ' + @tableName;
END
FETCH NEXT FROM cur INTO @tableName;
END
CLOSE cur;
DEALLOCATE cur;
GO
PRINT '=== Step 4: Create Indexes ===';
DECLARE @indexSql NVARCHAR(MAX);
DECLARE @tbl NVARCHAR(128);
DECLARE @idxName NVARCHAR(256);
DECLARE idxCur CURSOR FOR
SELECT name FROM sys.tables
WHERE name IN ('Customers', 'Jobs', 'Equipment', 'Quotes', 'InventoryItems', 'Suppliers', 'PricingTiers');
OPEN idxCur;
FETCH NEXT FROM idxCur INTO @tbl;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @idxName = 'IX_' + @tbl + '_CompanyId';
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = @idxName)
BEGIN
SET @indexSql = N'CREATE INDEX ' + QUOTENAME(@idxName) + N' ON ' + QUOTENAME(@tbl) + N'(CompanyId)';
EXEC sp_executesql @indexSql;
PRINT 'Created index ' + @idxName;
END
FETCH NEXT FROM idxCur INTO @tbl;
END
CLOSE idxCur;
DEALLOCATE idxCur;
GO
PRINT '=== Step 5: Add Foreign Keys ===';
-- AspNetUsers -> Companies
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE name = 'FK_AspNetUsers_Companies_CompanyId')
BEGIN
ALTER TABLE AspNetUsers
ADD CONSTRAINT FK_AspNetUsers_Companies_CompanyId
FOREIGN KEY (CompanyId) REFERENCES Companies(Id);
PRINT 'Added FK: AspNetUsers -> Companies';
END
-- All other tables -> Companies
DECLARE @fkSql NVARCHAR(MAX);
DECLARE @table NVARCHAR(128);
DECLARE @fkName NVARCHAR(256);
DECLARE fkCur CURSOR FOR
SELECT name FROM sys.tables
WHERE name IN ('Customers', 'Jobs', 'Equipment', 'Quotes', 'InventoryItems', 'Suppliers', 'PricingTiers');
OPEN fkCur;
FETCH NEXT FROM fkCur INTO @table;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @fkName = 'FK_' + @table + '_Companies_CompanyId';
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE name = @fkName)
BEGIN
SET @fkSql = N'ALTER TABLE ' + QUOTENAME(@table) +
N' ADD CONSTRAINT ' + QUOTENAME(@fkName) +
N' FOREIGN KEY (CompanyId) REFERENCES Companies(Id)';
EXEC sp_executesql @fkSql;
PRINT 'Added FK: ' + @table + ' -> Companies';
END
FETCH NEXT FROM fkCur INTO @table;
END
CLOSE fkCur;
DEALLOCATE fkCur;
GO
PRINT '=== Step 6: Update Migration History ===';
IF NOT EXISTS (SELECT * FROM __EFMigrationsHistory WHERE MigrationId = '20260206004522_AddMultiTenancyFixed')
BEGIN
INSERT INTO __EFMigrationsHistory (MigrationId, ProductVersion)
VALUES ('20260206004522_AddMultiTenancyFixed', '8.0.0');
PRINT 'Migration history updated';
END
GO
PRINT '';
PRINT '==============================================';
PRINT 'Multi-Tenancy Migration Completed Successfully!';
PRINT '==============================================';
PRINT 'Next steps:';
PRINT '1. Run the application: dotnet run --project src/PowderCoating.Web';
PRINT '2. Login with: superadmin@powdercoating.com / SuperAdmin123!';
PRINT '==============================================';
GO