diff --git a/src/Moryx.Products.Management/Implementation/RecipeManagement.cs b/src/Moryx.Products.Management/Implementation/RecipeManagement.cs index 4ac731fa..fe3a7fee 100644 --- a/src/Moryx.Products.Management/Implementation/RecipeManagement.cs +++ b/src/Moryx.Products.Management/Implementation/RecipeManagement.cs @@ -3,22 +3,25 @@ using System; using System.Collections.Generic; +using System.Linq; using Moryx.AbstractionLayer.Products; using Moryx.AbstractionLayer.Recipes; using Moryx.Container; +using Moryx.Model; using Moryx.Model.Repositories; using Moryx.Products.Model; +using Moryx.Workflows; namespace Moryx.Products.Management { - [Component(LifeCycle.Singleton, typeof(IRecipeManagement))] - internal class RecipeManagement : IRecipeManagement + [Component(LifeCycle.Singleton, typeof(IRecipeManagement), typeof(IWorkplans))] + internal class RecipeManagement : IRecipeManagement, IWorkplans { #region Dependencies public IProductStorage Storage { get; set; } - public IUnitOfWorkFactory UowFactory { get; set; } + public IUnitOfWorkFactory ModelFactory { get; set; } #endregion @@ -55,6 +58,72 @@ public void Save(long productId, ICollection recipes) RaiseRecipeChanged(recipe); } + public IReadOnlyList LoadAllWorkplans() + { + using (var uow = ModelFactory.Create()) + { + var repo = uow.GetRepository(); + var workplans = (from entity in repo.Linq.Active() + select new Workplan + { + Id = entity.Id, + Name = entity.Name, + Version = entity.Version, + State = (WorkplanState)entity.State + }).ToArray(); + return workplans; + } + } + + public Workplan LoadWorkplan(long workplanId) + { + using (var uow = ModelFactory.Create()) + { + return RecipeStorage.LoadWorkplan(uow, workplanId); + } + } + + public long SaveWorkplan(Workplan workplan) + { + using (var uow = ModelFactory.Create()) + { + var recipeRepo = uow.GetRepository(); + // Update all non-clone recipes of that workplan + var affectedRecipes = recipeRepo.Linq + .Where(r => r.WorkplanId == workplan.Id && r.Classification > 0).ToList(); + + var entity = RecipeStorage.SaveWorkplan(uow, workplan); + foreach (var recipe in affectedRecipes) + { + recipe.Workplan = entity; + } + + uow.SaveChanges(); + + foreach (var recipeEntity in affectedRecipes) + { + var recipe = Storage.LoadRecipe(recipeEntity.Id); + RaiseRecipeChanged(recipe); + } + + return entity.Id; + } + } + + public void DeleteWorkplan(long workplanId) + { + using (var uow = ModelFactory.Create()) + { + var repo = uow.GetRepository(); + var workplan = repo.GetByKey(workplanId); + if (workplan == null) + return; // TODO: Any feedback? + repo.Remove(workplan); + uow.SaveChanges(); + + } + } + private void RaiseRecipeChanged(IRecipe recipe) { // This must never be null diff --git a/src/Moryx.Products.Management/Implementation/RecipeStorage.cs b/src/Moryx.Products.Management/Implementation/RecipeStorage.cs index 19d1af06..107162cd 100644 --- a/src/Moryx.Products.Management/Implementation/RecipeStorage.cs +++ b/src/Moryx.Products.Management/Implementation/RecipeStorage.cs @@ -186,15 +186,19 @@ public static WorkplanEntity SaveWorkplan(IUnitOfWork uow, Workplan workplan) // If it is a new plan we need a new object if (workplanEntity == null) { - workplanEntity = workplanRepo.Create(workplan.Name, workplan.Version, (int)workplan.State); + workplanEntity = workplanRepo.Create(workplan.Name, 1, (int)workplan.State); EntityIdListener.Listen(workplanEntity, workplan); } - // If it was modified or the version increased we create a new one and reference the old one - else if (workplan.Version > workplanEntity.Version) + // If it was modified we write to a new entity and increment the version + else { + // Flag the previous version deleted, to hide it from the list but keep it accessible by old recipes + workplanRepo.Remove(workplanEntity); + + // Create a reference link between old and new version var reference = referenceRepo.Create((int)WorkplanReferenceType.NewVersion); reference.Source = workplanEntity; - reference.Target = workplanEntity = workplanRepo.Create(workplan.Name, workplan.Version, (int)workplan.State); + reference.Target = workplanEntity = workplanRepo.Create(workplan.Name, workplanEntity.Version + 1, (int)workplan.State); EntityIdListener.Listen(workplanEntity, workplan); } diff --git a/src/Moryx.Products.Management/Implementation/WorkplanManagement.cs b/src/Moryx.Products.Management/Implementation/WorkplanManagement.cs deleted file mode 100644 index 9ed5da25..00000000 --- a/src/Moryx.Products.Management/Implementation/WorkplanManagement.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2020, Phoenix Contact GmbH & Co. KG -// Licensed under the Apache License, Version 2.0 - -using System.Collections.Generic; -using System.Linq; -using Moryx.Container; -using Moryx.Model; -using Moryx.Model.Repositories; -using Moryx.Products.Model; -using Moryx.Workflows; - -namespace Moryx.Products.Management -{ - [Component(LifeCycle.Singleton, typeof(IWorkplans))] - internal class WorkplanManagement : IWorkplans - { - #region Dependencies - - public IUnitOfWorkFactory ModelFactory { get; set; } - - #endregion - - public IReadOnlyList LoadAllWorkplans() - { - using (var uow = ModelFactory.Create()) - { - var repo = uow.GetRepository(); - var workplans = (from entity in repo.Linq.Active() - select new Workplan - { - Id = entity.Id, - Name = entity.Name, - Version = entity.Version, - State = (WorkplanState)entity.State - }).ToArray(); - return workplans; - } - } - - public Workplan LoadWorkplan(long workplanId) - { - using (var uow = ModelFactory.Create()) - { - return RecipeStorage.LoadWorkplan(uow, workplanId); - } - } - - public long SaveWorkplan(Workplan workplan) - { - using (var uow = ModelFactory.Create()) - { - var entity = RecipeStorage.SaveWorkplan(uow, workplan); - - uow.SaveChanges(); - - return entity.Id; - } - } - - public void DeleteWorkplan(long workplanId) - { - using (var uow = ModelFactory.Create()) - { - var repo = uow.GetRepository(); - var workplan = repo.GetByKey(workplanId); - if (workplan == null) - return; // TODO: Any feedback? - repo.Remove(workplan); - uow.SaveChanges(); - - } - } - } -} diff --git a/src/Tests/Moryx.Products.IntegrationTests/RecipeStorage/RecipeStorageTests.cs b/src/Tests/Moryx.Products.IntegrationTests/RecipeStorage/RecipeStorageTests.cs index 382821ac..3998795c 100644 --- a/src/Tests/Moryx.Products.IntegrationTests/RecipeStorage/RecipeStorageTests.cs +++ b/src/Tests/Moryx.Products.IntegrationTests/RecipeStorage/RecipeStorageTests.cs @@ -29,18 +29,27 @@ public void FullCycle() var workplan = CreateWorkplan(); // Act - Workplan loaded; - WorkplanEntity entity; + Workplan loaded, loaded2; + WorkplanEntity entity1, entity2; using (var uow = _factory.Create()) { - entity = RecipeStorage.SaveWorkplan(uow, workplan); + entity1 = RecipeStorage.SaveWorkplan(uow, workplan); uow.SaveChanges(); - loaded = RecipeStorage.LoadWorkplan(uow, entity.Id); + loaded = RecipeStorage.LoadWorkplan(uow, entity1.Id); + + loaded.Name = "Modified"; + + entity2 = RecipeStorage.SaveWorkplan(uow, loaded); + uow.SaveChanges(); + loaded2 = RecipeStorage.LoadWorkplan(uow, entity2.Id); } // Assert - Assert.AreEqual(workplan.Id, entity.Id, "Id not assigned to original object!"); - Assert.AreEqual(workplan.Name, loaded.Name, "Name not correctly stored and saved"); + Assert.AreNotEqual(entity1.Id, entity2.Id); + Assert.AreEqual(workplan.Id, entity1.Id, "Id not assigned to original object!"); + Assert.AreEqual(workplan.Name, entity1.Name, "Name not correctly stored and saved"); + Assert.AreEqual(loaded.Name, entity2.Name, "Name not correctly stored and saved"); + Assert.AreEqual(loaded.Name, loaded2.Name, "Name not correctly stored and saved"); Assert.AreEqual(workplan.State, loaded.State); Assert.AreEqual(workplan.MaxElementId, loaded.MaxElementId);