diff --git a/DigitalLearningSolutions.Data.Migrations/202504281045_Alter_ReorderFrameworkCompetency.cs b/DigitalLearningSolutions.Data.Migrations/202504281045_Alter_ReorderFrameworkCompetency.cs new file mode 100644 index 0000000000..2759e056ac --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202504281045_Alter_ReorderFrameworkCompetency.cs @@ -0,0 +1,19 @@ + + +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + + [Migration(202504281045)] + public class Alter_ReorderFrameworkCompetency : Migration + { + public override void Up() + { + Execute.Sql(Properties.Resources.TD_5447_Alter_ReorderFrameworkCompetency_Up); + } + public override void Down() + { + Execute.Sql(Properties.Resources.TD_5447_Alter_ReorderFrameworkCompetency_Down); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/202504281115_UpdateFrameworkCompetenciesOrdering.cs b/DigitalLearningSolutions.Data.Migrations/202504281115_UpdateFrameworkCompetenciesOrdering.cs new file mode 100644 index 0000000000..e64cdd3f6f --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202504281115_UpdateFrameworkCompetenciesOrdering.cs @@ -0,0 +1,21 @@ +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + [Migration(202504281115)] + public class UpdateFrameworkCompetenciesOrdering : ForwardOnlyMigration + { + public override void Up() + { + Execute.Sql(@"WITH Ranked AS ( +    SELECT ID, +            ROW_NUMBER() OVER (PARTITION BY FrameworkID ORDER BY SysStartTime) AS NewOrder +    FROM FrameworkCompetencies + Where FrameworkCompetencyGroupID is null + ) + UPDATE fc + SET fc.Ordering = r.NewOrder + FROM FrameworkCompetencies fc + JOIN Ranked r ON fc.ID = r.ID;"); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs index ea8a97cc31..f5949119d4 100644 --- a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs +++ b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs @@ -2436,6 +2436,50 @@ internal static string TD_5412_Alter_SendExpiredTBCReminders_Up { } } + /// + /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[ReorderFrameworkCompetency] Script Date: 24/04/2025 09:23:17 ******/ + ///SET ANSI_NULLS ON + ///GO + /// + ///SET QUOTED_IDENTIFIER ON + ///GO + /// + ///-- ============================================= + ///-- Author: Kevin Whittaker + ///-- Create date: 04/01/2021 + ///-- Description: Reorders the FrameworkCompetencies in a given FrameworkCompetencyGroup - moving the given competency up or down. + ///-- ============================================= + ///ALTER PROCEDURE [dbo].[ReorderFrameworkCompetency] + /// [rest of string was truncated]";. + /// + internal static string TD_5447_Alter_ReorderFrameworkCompetency_Down { + get { + return ResourceManager.GetString("TD_5447_Alter_ReorderFrameworkCompetency_Down", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[ReorderFrameworkCompetency] Script Date: 24/04/2025 09:23:17 ******/ + ///SET ANSI_NULLS ON + ///GO + /// + ///SET QUOTED_IDENTIFIER ON + ///GO + /// + ///-- ============================================= + ///-- Author: Kevin Whittaker + ///-- Create date: 04/01/2021 + ///-- Description: Reorders the FrameworkCompetencies in a given FrameworkCompetencyGroup - moving the given competency up or down. + ///-- ============================================= + ///ALTER PROCEDURE [dbo].[ReorderFrameworkCompetency] + /// [rest of string was truncated]";. + /// + internal static string TD_5447_Alter_ReorderFrameworkCompetency_Up { + get { + return ResourceManager.GetString("TD_5447_Alter_ReorderFrameworkCompetency_Up", resourceCulture); + } + } + /// /// Looks up a localized string similar to /****** Object: StoredProcedure [dbo].[SendExpiredTBCReminders] Script Date: 16/04/2025 10:50:12 ******/ ///SET ANSI_NULLS ON diff --git a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx index df856a17ae..c0b77842ad 100644 --- a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx +++ b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx @@ -481,4 +481,10 @@ ..\Scripts\TD-5514-Alter_SendExpiredTBCReminders_Up.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + ..\Scripts\TD-5447-Alter_ReorderFrameworkCompetency_Down.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\Scripts\TD-5447-Alter_ReorderFrameworkCompetency_Up.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + \ No newline at end of file diff --git a/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Down.sql b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Down.sql new file mode 100644 index 0000000000..56bac72b67 Binary files /dev/null and b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Down.sql differ diff --git a/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Up.sql b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Up.sql new file mode 100644 index 0000000000..bd170f6b9e Binary files /dev/null and b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5447-Alter_ReorderFrameworkCompetency_Up.sql differ diff --git a/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs b/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs index a925a1e867..3b8d0fa8a4 100644 --- a/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/FrameworkDataService.cs @@ -252,9 +252,9 @@ string direction void RemoveCustomFlag(int flagId); void RemoveCollaboratorFromFramework(int frameworkId, int id); - void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId); + void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId); - void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId); + void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId); void DeleteFrameworkDefaultQuestion( int frameworkId, @@ -689,9 +689,11 @@ public int InsertFrameworkCompetency( var numberOfAffectedRows = connection.Execute( @"INSERT INTO FrameworkCompetencies ([CompetencyID], FrameworkCompetencyGroupID, UpdatedByAdminID, Ordering, FrameworkID) VALUES (@competencyId, @frameworkCompetencyGroupID, @adminId, COALESCE - ((SELECT MAX(Ordering) AS OrderNum - FROM [FrameworkCompetencies] - WHERE ([FrameworkCompetencyGroupID] = @frameworkCompetencyGroupID)), 0)+1, @frameworkId)", + ((SELECT MAX(Ordering) AS OrderNum + FROM [FrameworkCompetencies] + WHERE ((@frameworkCompetencyGroupID IS NULL AND FrameworkCompetencyGroupID IS NULL) OR + (@frameworkCompetencyGroupID IS NOT NULL AND FrameworkCompetencyGroupID = @frameworkCompetencyGroupID)) AND + FrameworkID = @frameworkId ), 0)+1, @frameworkId)", new { competencyId, frameworkCompetencyGroupID, adminId, frameworkId } ); if (numberOfAffectedRows < 1) @@ -1143,7 +1145,7 @@ public void MoveFrameworkCompetency(int frameworkCompetencyId, bool singleStep, ); } - public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId) + public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId) { if ((frameworkCompetencyGroupId < 1) | (adminId < 1)) { @@ -1174,7 +1176,23 @@ public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int c new { frameworkCompetencyGroupId } ); - if (numberOfAffectedRows < 1) + if (numberOfAffectedRows > 0) + { + connection.Execute( + @"WITH Ranked AS ( +    SELECT ID, +            ROW_NUMBER() OVER (PARTITION BY FrameworkID ORDER BY Ordering) AS NewOrder +    FROM FrameworkCompetencyGroups + Where FrameworkID = @frameworkID + ) + UPDATE fcg + SET fcg.Ordering = r.NewOrder + FROM FrameworkCompetencyGroups fcg + JOIN Ranked r ON fcg.ID = r.ID;", + new { frameworkId } + ); + } + else { logger.LogWarning( "Not deleting framework competency group as db update failed. " + @@ -1219,7 +1237,7 @@ public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int c } } - public void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId) + public void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId) { var competencyId = connection.QuerySingle( @"SELECT CompetencyID FROM FrameworkCompetencies WHERE ID = @frameworkCompetencyId", @@ -1243,7 +1261,24 @@ public void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId) @"DELETE FROM FrameworkCompetencies WHERE ID = @frameworkCompetencyId", new { frameworkCompetencyId } ); - if (numberOfAffectedRows < 1) + if (numberOfAffectedRows > 0) + { + connection.Execute( + @"WITH Ranked AS ( +    SELECT ID, +            ROW_NUMBER() OVER (PARTITION BY FrameworkID ORDER BY Ordering) AS NewOrder +    FROM FrameworkCompetencies + Where (FrameworkCompetencyGroupID = @frameworkCompetencyGroupID) OR (FrameworkCompetencyGroupID IS NULL AND @frameworkCompetencyGroupID IS NULL) AND + FrameworkID = @frameworkID + ) + UPDATE fc + SET fc.Ordering = r.NewOrder + FROM FrameworkCompetencies fc + JOIN Ranked r ON fc.ID = r.ID;", + new { frameworkCompetencyGroupId, frameworkId } + ); + } + else { logger.LogWarning( "Not deleting framework competency as db update failed. " + diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs index 6afd88f86a..0893c7f7c6 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs @@ -102,7 +102,7 @@ public IActionResult DeleteFrameworkCompetencyGroup(int frameworkId, int compete var adminId = GetAdminId(); - frameworkService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, adminId); + frameworkService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, frameworkId, adminId); return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId })); } @@ -235,7 +235,7 @@ public IActionResult DeleteFrameworkCompetency(int frameworkId, int frameworkCom { var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); if (userRole < 2) return StatusCode(403); - frameworkService.DeleteFrameworkCompetency(frameworkCompetencyId, GetAdminId()); + frameworkService.DeleteFrameworkCompetency(frameworkCompetencyId, frameworkCompetencyGroupId, frameworkId, GetAdminId()); return frameworkCompetencyGroupId != null ? new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()) : new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fc-ungrouped"); } [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId:int=0}/{frameworkCompetencyId}/Preview/")] diff --git a/DigitalLearningSolutions.Web/Services/FrameworkService.cs b/DigitalLearningSolutions.Web/Services/FrameworkService.cs index b407be417f..6e2c1790e9 100644 --- a/DigitalLearningSolutions.Web/Services/FrameworkService.cs +++ b/DigitalLearningSolutions.Web/Services/FrameworkService.cs @@ -247,9 +247,9 @@ string direction void RemoveCustomFlag(int flagId); void RemoveCollaboratorFromFramework(int frameworkId, int id); - void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId); + void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId); - void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId); + void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId); void DeleteFrameworkDefaultQuestion( int frameworkId, @@ -316,14 +316,14 @@ public void DeleteCompetencyLearningResource(int competencyLearningResourceId, i frameworkDataService.DeleteCompetencyLearningResource(competencyLearningResourceId, adminId); } - public void DeleteFrameworkCompetency(int frameworkCompetencyId, int adminId) + public void DeleteFrameworkCompetency(int frameworkCompetencyId, int? frameworkCompetencyGroupId, int frameworkId, int adminId) { - frameworkDataService.DeleteFrameworkCompetency(frameworkCompetencyId, adminId); + frameworkDataService.DeleteFrameworkCompetency(frameworkCompetencyId, frameworkCompetencyGroupId, frameworkId, adminId); } - public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int adminId) + public void DeleteFrameworkCompetencyGroup(int frameworkCompetencyGroupId, int competencyGroupId, int frameworkId, int adminId) { - frameworkDataService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, adminId); + frameworkDataService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, frameworkId, adminId); } public void DeleteFrameworkDefaultQuestion(int frameworkId, int assessmentQuestionId, int adminId, bool deleteFromExisting)