195 lines
6.2 KiB
Transact-SQL
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
|