diff --git a/src/Infrastructure.EntityFramework/AdminConsole/Configurations/CollectionEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/AdminConsole/Configurations/CollectionEntityTypeConfiguration.cs index 24c56ac4e1..11975a1b9e 100644 --- a/src/Infrastructure.EntityFramework/AdminConsole/Configurations/CollectionEntityTypeConfiguration.cs +++ b/src/Infrastructure.EntityFramework/AdminConsole/Configurations/CollectionEntityTypeConfiguration.cs @@ -18,6 +18,14 @@ public class CollectionEntityTypeConfiguration : IEntityTypeConfiguration() + .WithMany() + .HasForeignKey(c => c.DefaultCollectionOwner) + .OnDelete(DeleteBehavior.NoAction); + builder.ToTable(nameof(Collection)); } } \ No newline at end of file diff --git a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs index ae55099775..c8c453f224 100644 --- a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs +++ b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs @@ -114,7 +114,8 @@ public class OrganizationUserRepository : Repository c.Type, CollectionType.SharedCollection) .SetProperty(c => c.RevisionDate, utcNow) .SetProperty(c => c.DefaultUserCollectionEmail, - c => c.DefaultUserCollectionEmail == null ? email : c.DefaultUserCollectionEmail)); + c => c.DefaultUserCollectionEmail == null ? email : c.DefaultUserCollectionEmail) + .SetProperty(c => c.DefaultCollectionOwner, (Guid?)null)); await dbContext.CollectionUsers .Where(cu => cu.OrganizationUserId == organizationUser.Id) diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_MigrateDefaultCollection.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_MigrateDefaultCollection.sql index f65cdc3983..16be582485 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_MigrateDefaultCollection.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_MigrateDefaultCollection.sql @@ -9,7 +9,8 @@ BEGIN SET [DefaultUserCollectionEmail] = CASE WHEN c.[DefaultUserCollectionEmail] IS NULL THEN u.[Email] ELSE c.[DefaultUserCollectionEmail] END, [RevisionDate] = @UtcNow, - [Type] = 0 + [Type] = 0, + [DefaultCollectionOwner] = NULL FROM [dbo].[Collection] c INNER JOIN [dbo].[CollectionUser] cu ON c.[Id] = cu.[CollectionId] diff --git a/src/Sql/dbo/Tables/Collection.sql b/src/Sql/dbo/Tables/Collection.sql index be9a39278e..9b3009d4fe 100644 --- a/src/Sql/dbo/Tables/Collection.sql +++ b/src/Sql/dbo/Tables/Collection.sql @@ -10,7 +10,7 @@ [DefaultCollectionOwner] UNIQUEIDENTIFIER NULL, CONSTRAINT [PK_Collection] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_Collection_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE, - CONSTRAINT [FK_Collection_OrganizationUser] FOREIGN KEY ([DefaultCollectionOwner]) REFERENCES [dbo].[OrganizationUser] ([Id]) ON DELETE SET NULL + CONSTRAINT [FK_Collection_OrganizationUser] FOREIGN KEY ([DefaultCollectionOwner]) REFERENCES [dbo].[OrganizationUser] ([Id]) ON DELETE NO ACTION ); GO diff --git a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/OrganizationUserRepositoryTests.cs b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/OrganizationUserRepositoryTests.cs index 68d1b29c68..717eafc430 100644 --- a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/OrganizationUserRepositoryTests.cs +++ b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/OrganizationUserRepositoryTests.cs @@ -147,11 +147,13 @@ public class OrganizationUserRepositoryTests Assert.NotNull(updatedCollection1); Assert.Equal(CollectionType.SharedCollection, updatedCollection1.Type); Assert.Equal(user1.Email, updatedCollection1.DefaultUserCollectionEmail); + Assert.Null(updatedCollection1.DefaultCollectionOwner); var updatedCollection2 = await collectionRepository.GetByIdAsync(defaultUserCollection2.Id); Assert.NotNull(updatedCollection2); Assert.Equal(CollectionType.SharedCollection, updatedCollection2.Type); Assert.Equal(user2.Email, updatedCollection2.DefaultUserCollectionEmail); + Assert.Null(updatedCollection2.DefaultCollectionOwner); } [DatabaseTheory, DatabaseData] @@ -214,6 +216,7 @@ public class OrganizationUserRepositoryTests Assert.NotNull(updatedCollection); Assert.Equal(CollectionType.SharedCollection, updatedCollection.Type); Assert.Equal(user.Email, updatedCollection.DefaultUserCollectionEmail); + Assert.Null(updatedCollection.DefaultCollectionOwner); } @@ -1355,6 +1358,7 @@ public class OrganizationUserRepositoryTests Assert.NotNull(updatedCollection); Assert.Equal(CollectionType.SharedCollection, updatedCollection.Type); Assert.Equal(user.Email, updatedCollection.DefaultUserCollectionEmail); + Assert.Null(updatedCollection.DefaultCollectionOwner); } [DatabaseTheory, DatabaseData] @@ -1412,6 +1416,7 @@ public class OrganizationUserRepositoryTests Assert.NotNull(updatedCollection); Assert.Equal(CollectionType.SharedCollection, updatedCollection.Type); Assert.Equal(user.Email, updatedCollection.DefaultUserCollectionEmail); + Assert.Null(updatedCollection.DefaultCollectionOwner); } [DatabaseTheory, DatabaseData] diff --git a/util/Migrator/DbScripts/2025-12-20_00_Collection_AddDefaultCollectionOwnerAndConstraint.sql b/util/Migrator/DbScripts/2025-12-20_00_Collection_AddDefaultCollectionOwnerAndConstraint.sql index 5144d0515f..476c91b56e 100644 --- a/util/Migrator/DbScripts/2025-12-20_00_Collection_AddDefaultCollectionOwnerAndConstraint.sql +++ b/util/Migrator/DbScripts/2025-12-20_00_Collection_AddDefaultCollectionOwnerAndConstraint.sql @@ -26,7 +26,7 @@ BEGIN ADD CONSTRAINT [FK_Collection_OrganizationUser] FOREIGN KEY ([DefaultCollectionOwner]) REFERENCES [dbo].[OrganizationUser] ([Id]) - ON DELETE SET NULL + ON DELETE NO ACTION END GO diff --git a/util/Migrator/DbScripts/2025-12-20_02_OrganizationUser_MigrateDefaultCollection.sql b/util/Migrator/DbScripts/2025-12-20_02_OrganizationUser_MigrateDefaultCollection.sql new file mode 100644 index 0000000000..4f90b6d251 --- /dev/null +++ b/util/Migrator/DbScripts/2025-12-20_02_OrganizationUser_MigrateDefaultCollection.sql @@ -0,0 +1,26 @@ +-- Update OrganizationUser_MigrateDefaultCollection to set DefaultCollectionOwner = NULL +-- when migrating default collections to shared collections during OrganizationUser deletion + +CREATE OR ALTER PROCEDURE [dbo].[OrganizationUser_MigrateDefaultCollection] + @Ids [dbo].[GuidIdArray] READONLY +AS +BEGIN + SET NOCOUNT ON + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); + + UPDATE c + SET + [DefaultUserCollectionEmail] = CASE WHEN c.[DefaultUserCollectionEmail] IS NULL THEN u.[Email] ELSE c.[DefaultUserCollectionEmail] END, + [RevisionDate] = @UtcNow, + [Type] = 0, + [DefaultCollectionOwner] = NULL + FROM + [dbo].[Collection] c + INNER JOIN [dbo].[CollectionUser] cu ON c.[Id] = cu.[CollectionId] + INNER JOIN [dbo].[OrganizationUser] ou ON cu.[OrganizationUserId] = ou.[Id] + INNER JOIN [dbo].[User] u ON ou.[UserId] = u.[Id] + INNER JOIN @Ids i ON ou.[Id] = i.[Id] + WHERE + c.[Type] = 1 +END +GO \ No newline at end of file