-- Tables -- ON DELETE CASCADE is intentional on both foreign keys: a deleted Organization should not -- block deletion or leave orphaned assignment rows, and a deleted Cohort should drop its -- assignment rows with it (cohorts and their assignments share a lifecycle). IF OBJECT_ID('[dbo].[OrganizationPlanMigrationCohort]') IS NULL BEGIN CREATE TABLE [dbo].[OrganizationPlanMigrationCohort] ( [Id] UNIQUEIDENTIFIER NOT NULL, [Name] NVARCHAR(255) NOT NULL, [MigrationPathId] TINYINT NULL, [ProactiveDiscountCouponCode] NVARCHAR(64) NULL, [ChurnDiscountCouponCode] NVARCHAR(64) NULL, [IsActive] BIT NOT NULL CONSTRAINT [DF_OrganizationPlanMigrationCohort_IsActive] DEFAULT (0), [CreationDate] DATETIME2(7) NOT NULL, [RevisionDate] DATETIME2(7) NOT NULL, CONSTRAINT [PK_OrganizationPlanMigrationCohort] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [IX_OrganizationPlanMigrationCohort_Name] UNIQUE ([Name]) ); END GO IF OBJECT_ID('[dbo].[OrganizationPlanMigrationCohortAssignment]') IS NULL BEGIN CREATE TABLE [dbo].[OrganizationPlanMigrationCohortAssignment] ( [Id] UNIQUEIDENTIFIER NOT NULL, [OrganizationId] UNIQUEIDENTIFIER NOT NULL, [CohortId] UNIQUEIDENTIFIER NOT NULL, [ScheduledDate] DATETIME2(7) NULL, [MigratedDate] DATETIME2(7) NULL, [ChurnDiscountAppliedDate] DATETIME2(7) NULL, [CreationDate] DATETIME2(7) NOT NULL, [RevisionDate] DATETIME2(7) NOT NULL, CONSTRAINT [PK_OrganizationPlanMigrationCohortAssignment] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_OrganizationPlanMigrationCohortAssignment_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE, CONSTRAINT [FK_OrganizationPlanMigrationCohortAssignment_Cohort] FOREIGN KEY ([CohortId]) REFERENCES [dbo].[OrganizationPlanMigrationCohort] ([Id]) ON DELETE CASCADE, CONSTRAINT [IX_OrganizationPlanMigrationCohortAssignment_OrganizationId] UNIQUE ([OrganizationId]) ); END GO -- Composite index supports the Pending/Scheduled/Migrated counts query consumed by -- the Cohort Management aggregate (PM-36951). Land it here so the consumer does not -- need a follow-up ALTER migration. IF NOT EXISTS ( SELECT 1 FROM sys.indexes WHERE name = 'IX_OrganizationPlanMigrationCohortAssignment_CohortId_ScheduledDate_MigratedDate' AND object_id = OBJECT_ID('[dbo].[OrganizationPlanMigrationCohortAssignment]') ) BEGIN CREATE NONCLUSTERED INDEX [IX_OrganizationPlanMigrationCohortAssignment_CohortId_ScheduledDate_MigratedDate] ON [dbo].[OrganizationPlanMigrationCohortAssignment] ([CohortId] ASC, [ScheduledDate] ASC, [MigratedDate] ASC); END GO -- Views CREATE OR ALTER VIEW [dbo].[OrganizationPlanMigrationCohortView] AS SELECT * FROM [dbo].[OrganizationPlanMigrationCohort] GO CREATE OR ALTER VIEW [dbo].[OrganizationPlanMigrationCohortAssignmentView] AS SELECT * FROM [dbo].[OrganizationPlanMigrationCohortAssignment] GO -- Stored Procedures: OrganizationPlanMigrationCohort CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohort_Create] @Id UNIQUEIDENTIFIER OUTPUT, @Name NVARCHAR(255), @MigrationPathId TINYINT, @ProactiveDiscountCouponCode NVARCHAR(64), @ChurnDiscountCouponCode NVARCHAR(64), @IsActive BIT, @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) AS BEGIN SET NOCOUNT ON INSERT INTO [dbo].[OrganizationPlanMigrationCohort] ( [Id], [Name], [MigrationPathId], [ProactiveDiscountCouponCode], [ChurnDiscountCouponCode], [IsActive], [CreationDate], [RevisionDate] ) VALUES ( @Id, @Name, @MigrationPathId, @ProactiveDiscountCouponCode, @ChurnDiscountCouponCode, @IsActive, @CreationDate, @RevisionDate ) END GO CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohort_ReadById] @Id UNIQUEIDENTIFIER AS BEGIN SET NOCOUNT ON SELECT * FROM [dbo].[OrganizationPlanMigrationCohortView] WHERE [Id] = @Id END GO CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohort_Update] @Id UNIQUEIDENTIFIER, @Name NVARCHAR(255), @MigrationPathId TINYINT, @ProactiveDiscountCouponCode NVARCHAR(64), @ChurnDiscountCouponCode NVARCHAR(64), @IsActive BIT, @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) AS BEGIN SET NOCOUNT ON -- @CreationDate is accepted but not assigned; it is immutable once the row is inserted. UPDATE [dbo].[OrganizationPlanMigrationCohort] SET [Name] = @Name, [MigrationPathId] = @MigrationPathId, [ProactiveDiscountCouponCode] = @ProactiveDiscountCouponCode, [ChurnDiscountCouponCode] = @ChurnDiscountCouponCode, [IsActive] = @IsActive, [RevisionDate] = @RevisionDate WHERE [Id] = @Id END GO CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohort_DeleteById] @Id UNIQUEIDENTIFIER AS BEGIN SET NOCOUNT ON DELETE FROM [dbo].[OrganizationPlanMigrationCohort] WHERE [Id] = @Id END GO -- Stored Procedures: OrganizationPlanMigrationCohortAssignment CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohortAssignment_Create] @Id UNIQUEIDENTIFIER OUTPUT, @OrganizationId UNIQUEIDENTIFIER, @CohortId UNIQUEIDENTIFIER, @ScheduledDate DATETIME2(7), @MigratedDate DATETIME2(7), @ChurnDiscountAppliedDate DATETIME2(7), @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) AS BEGIN SET NOCOUNT ON INSERT INTO [dbo].[OrganizationPlanMigrationCohortAssignment] ( [Id], [OrganizationId], [CohortId], [ScheduledDate], [MigratedDate], [ChurnDiscountAppliedDate], [CreationDate], [RevisionDate] ) VALUES ( @Id, @OrganizationId, @CohortId, @ScheduledDate, @MigratedDate, @ChurnDiscountAppliedDate, @CreationDate, @RevisionDate ) END GO CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohortAssignment_ReadById] @Id UNIQUEIDENTIFIER AS BEGIN SET NOCOUNT ON SELECT * FROM [dbo].[OrganizationPlanMigrationCohortAssignmentView] WHERE [Id] = @Id END GO CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohortAssignment_Update] @Id UNIQUEIDENTIFIER, @OrganizationId UNIQUEIDENTIFIER, @CohortId UNIQUEIDENTIFIER, @ScheduledDate DATETIME2(7), @MigratedDate DATETIME2(7), @ChurnDiscountAppliedDate DATETIME2(7), @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) AS BEGIN SET NOCOUNT ON -- @OrganizationId, @CohortId, and @CreationDate are accepted but not assigned; they are -- immutable once the row is inserted. The assignment-to-cohort and assignment-to-org -- relationships cannot be changed after creation -- create a new row instead. UPDATE [dbo].[OrganizationPlanMigrationCohortAssignment] SET [ScheduledDate] = @ScheduledDate, [MigratedDate] = @MigratedDate, [ChurnDiscountAppliedDate] = @ChurnDiscountAppliedDate, [RevisionDate] = @RevisionDate WHERE [Id] = @Id END GO CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohortAssignment_DeleteById] @Id UNIQUEIDENTIFIER AS BEGIN SET NOCOUNT ON DELETE FROM [dbo].[OrganizationPlanMigrationCohortAssignment] WHERE [Id] = @Id END GO CREATE OR ALTER PROCEDURE [dbo].[OrganizationPlanMigrationCohortAssignment_ReadByOrganizationId] @OrganizationId UNIQUEIDENTIFIER AS BEGIN SET NOCOUNT ON SELECT * FROM [dbo].[OrganizationPlanMigrationCohortAssignmentView] WHERE [OrganizationId] = @OrganizationId END GO