public static void CheckObjectStateManagerState(KsmedEntities context, EntityState expectedState, IEnumerable <object> entities) { foreach (var entity in entities) { Debug.Assert(context.ObjectStateManager.GetObjectStateEntry(entity).State == expectedState); } }
/// <summary> /// Obtient la durée process des actions spécifiées. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="ids">Les identifiants.</param> /// <returns>Les durées</returns> internal static async Task <ActionDuration[]> GetActionsBuildDurations(KsmedEntities context, IEnumerable <int> ids) { StringBuilder query = new StringBuilder(); query.Append("SELECT a.ActionId, a.BuildFinish, a.BuildStart FROM KActions AS a WHERE a.ActionId IN { "); foreach (int id in ids) { query.Append(id); query.Append(", "); } query.Remove(query.Length - 2, 2); query.Append(" }"); // Initialise l'OSpace context.CreateQuery <KAction>(KsmedEntities.KActionsEntitySetName); return((await new ObjectQuery <DbDataRecord>(query.ToString(), context).ExecuteAsync(MergeOption.NoTracking)) .Select(dbdr => new ActionDuration { ActionId = dbdr.GetInt32(0), BuildDuration = dbdr.GetInt64(1) - dbdr.GetInt64(2), }).ToArray()); }
/// <summary> /// Obtient les données pour l'écran Simuler. /// </summary> /// <param name="context">le contexte EF.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <param name="natureFilter">Le filtre des codes de nature.</param> /// <returns> /// Les données /// </returns> public static async Task <SimulateData> GetSimulateData(KsmedEntities context, int projectId, GetDataScenarioNatures natureFilter) { IDictionary <ProcessReferentialIdentifier, bool> referentialsUsed = await GetReferentialsUse(context, projectId); await Queries.LoadAllReferentialsOfProject(context, projectId, referentialsUsed); await context.Projects .Include(nameof(Project.Process)) .Include($"{nameof(Project.Process)}.{nameof(Procedure.Videos)}") .Where(p => p.ProjectId == projectId) .SelectMany(p => p.Process.Videos) .ToArrayAsync(); Scenario[] scenarios = await LoadScenarios(context, projectId, referentialsUsed, natureFilter); Project project = await context.Projects.SingleAsync(p => p.ProjectId == projectId); ScenarioActionHierarchyHelper.MapScenariosActionsOriginals(scenarios); SimulateData data = new SimulateData() { Scenarios = scenarios, ActionTypes = await context.ActionTypes.ToArrayAsync(), CustomFieldsLabels = GetCustomFieldsLabels(project), }; return(data); }
/// <summary> /// Crée un scénario cible à partir d'un autre scénario, initial ou cible. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <param name="sourceScenarioId">L'identifiant du scénario source.</param> /// <param name="natureCode">Le code de la nature.</param> /// <param name="save"><c>true</c> pour sauvegarder le scénario créé.</param> /// <returns> /// Le scénario créé /// </returns> public static async Task <Scenario> CreateDerivatedScenario(KsmedEntities context, int projectId, int sourceScenarioId, string natureCode, bool save) { Scenario fromScenario; using (var tempContext = ContextFactory.GetNewContext()) { // Charger les référentiels var referentialsUsed = await SharedScenarioActionsOperations.GetReferentialsUse(context, projectId); await Queries.LoadAllReferentialsOfProject(context, projectId, referentialsUsed); var videos = await context.Projects .Include(nameof(Project.Process)) .Include($"{nameof(Project.Process)}.{nameof(Procedure.Videos)}") .Where(p => p.ProjectId == projectId) .SelectMany(p => p.Process.Videos) .ToArrayAsync(); fromScenario = await context.Scenarios.FirstAsync(s => s.ScenarioId == sourceScenarioId); await Queries.LoadScenariosDetails(context, EnumerableExt.Concat(fromScenario), referentialsUsed); } return(await CreateDerivatedScenario(context, fromScenario, natureCode, save)); }
/// <summary> /// Obtient les données pour l'écran Construire. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <param name="natureFilter">Le filtre sur les codes de nature de scénario.</param> /// <returns>Les données</returns> public static async Task <BuildData> GetBuildData(KsmedEntities context, int projectId, GetDataScenarioNatures natureFilter) { IDictionary <ProcessReferentialIdentifier, bool> referentialsUsed = await GetReferentialsUse(context, projectId); Referentials referentials = await Queries.LoadAllReferentialsOfProject(context, projectId, referentialsUsed); BuildData data = new BuildData { Categories = referentials.Categories, Skills = referentials.Skills, Resources = referentials.Resources, Videos = await context.Projects .Include(nameof(Project.Process)) .Include($"{nameof(Project.Process)}.{nameof(Procedure.Videos)}") .Where(p => p.ProjectId == projectId) .SelectMany(p => p.Process.Videos) .ToArrayAsync(), ActionTypes = (await context.ActionTypes.ToArrayAsync()).OrderBy(a => a.ActionTypeCode, new KnownActionCategoryTypes.ActionCategoryTypeDefaultOrderComparer()).ToArray() }; Project project = await context.Projects.SingleAsync(p => p.ProjectId == projectId); data.CustomFieldsLabels = GetCustomFieldsLabels(project); Scenario[] scenarios = await LoadScenarios(context, projectId, referentialsUsed, natureFilter); ScenarioActionHierarchyHelper.MapScenariosActionsOriginals(scenarios); data.Scenarios = scenarios; return(data); }
/// <summary> /// Crée une instance de <see cref="ProjectExport"/>. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <returns>Le <see cref="ProjectExport"/></returns> internal async Task <ProjectExport> CreateProjectExport(KsmedEntities context, int projectId) { var referentialsUsed = await SharedScenarioActionsOperations.GetReferentialsUse(context, projectId); await Queries.LoadAllReferentialsOfProject(context, projectId, referentialsUsed); var project = await context.Projects .Include("Videos") .Include("Referentials") .FirstAsync(s => s.ProjectId == projectId); var scenarios = await context.Scenarios .Where(s => s.ProjectId == projectId && (s.NatureCode == KnownScenarioNatures.Initial || s.NatureCode == KnownScenarioNatures.Target || s.NatureCode == KnownScenarioNatures.Realized)) .ToArrayAsync(); await Queries.LoadScenariosDetails(context, scenarios, referentialsUsed); return(new ProjectExport() { AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), Project = project, ReferentialsStandard = ReferentialsHelper.GetAllReferentialsStandardUsed(project).ToArray(), ReferentialsProject = ReferentialsHelper.GetAllReferentialsProject(project).ToArray(), }); }
/// <summary> /// Constructeur. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <param name="scenarioId">L'identifiant du scénario.</param> /// <param name="videoId">L'identifiant de la vidéo.</param> public VideoDecompositionExporter(KsmedEntities context, int projectId, int scenarioId, int videoId) { _context = context; _projectId = projectId; _scenarioId = scenarioId; _videoId = videoId; }
/// <summary> /// Constructeur. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="import">La décomposition vidéo à importer.</param> /// <param name="targetScenario">Le scénario cible.</param> public VideoDecompositionImporter(KsmedEntities context, VideoDecompositionImport import, Scenario targetScenario) { _context = context; _import = import; _targetScenario = targetScenario; _referentialsToRemap = new Dictionary <IActionReferential, IActionReferential>(); }
/// <summary> /// Crée un scénario cible à partir d'un autre scénario, initial ou cible. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="sourceScenario">Le scenario source.</param> /// <param name="natureCode">Le code de la nature.</param> /// <param name="save"><c>true</c> pour sauvegarder le scénario créé.</param> /// <returns> /// Le scénario créé /// </returns> public static async Task <Scenario> CreateDerivatedScenario(KsmedEntities context, Scenario sourceScenario, string natureCode, bool save) { var targetNumber = await context.Scenarios.Where(s => s.ProjectId == sourceScenario.ProjectId && s.NatureCode == natureCode) .CountAsync() + 1; return(await CreateDerivatedScenario(context, sourceScenario, natureCode, save, targetNumber)); }
public static void CheckNotInContext(KsmedEntities context, IEnumerable <object> entities) { // S'assurer que pour les référentiels mergés, il n'y a pas de trace d'eux dans le contexte foreach (var entity in entities) { Debug.Assert(!context.ObjectStateManager.TryGetObjectStateEntry(entity, out ObjectStateEntry entry)); } }
/// <summary> /// Obtient les données pour l'écran Restituer. /// </summary> /// <param name="context">le contexte EF.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <returns> /// Les données /// </returns> public static async Task <RestitutionData> GetRestitutionData(KsmedEntities context, int projectId) { IDictionary <ProcessReferentialIdentifier, bool> referentialsUsed = await GetReferentialsUse(context, projectId); Referentials referentials = await Queries.LoadAllReferentialsOfProject(context, projectId, referentialsUsed); ActionCategory[] categories = referentials.Categories; await context.Projects .Include(nameof(Project.Process)) .Include($"{nameof(Project.Process)}.{nameof(Procedure.Videos)}") .Where(p => p.ProjectId == projectId) .SelectMany(p => p.Process.Videos) .ToArrayAsync(); Scenario[] scenarios = await context.Scenarios .Where(s => s.ProjectId == projectId) .ToArrayAsync(); await Queries.LoadScenariosDetails(context, scenarios, referentialsUsed); ILookup <int, KAction> actionsToLoad = scenarios .SelectMany(a => a.Actions) .Where(a => a.IsReduced && a.OriginalActionId.HasValue) .ToLookup(a => a.OriginalActionId.Value, a => a); if (actionsToLoad.Any()) { foreach (ActionDuration duration in await GetActionsBuildDurations(context, actionsToLoad.Select(g => g.Key))) { foreach (KAction action in actionsToLoad[duration.ActionId]) { action.Reduced.Saving = duration.BuildDuration - action.BuildDuration; } } } ScenarioActionHierarchyHelper.MapScenariosActionsOriginals(scenarios); foreach (Scenario scenario in scenarios) { UpdateIsGroup(scenario); } RestitutionData data = new RestitutionData() { Scenarios = scenarios, ActionCategories = categories, }; return(data); }
/// <summary> /// Charge les référentiels du projet spécifié dans le contexte. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <param name="referentialsUse">Les référentiels utilisés, ou <c>null</c> pour les utiliser tous.</param> /// <returns>Les référentiels chargés.</returns> internal static async Task <Referentials> LoadAllReferentialsOfProject(KsmedEntities context, int projectId, IDictionary <ProcessReferentialIdentifier, bool> referentialsUse) { bool isNull = referentialsUse == null; int processId = (await context.Projects.SingleAsync(p => p.ProjectId == projectId)).ProcessId; Referentials results = new Referentials { // Toujours actif Categories = await FilterReferentials(context.ActionCategories, processId, ProcessReferentialIdentifier.Category).ToArrayAsync(), Skills = await FilterReferentials(context.Skills, processId, ProcessReferentialIdentifier.Skill).ToArrayAsync(), Resources = await FilterResources(context, processId).ToArrayAsync() }; if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref1]) { results.Ref1s = await FilterReferentials(context.Refs1, processId, ProcessReferentialIdentifier.Ref1).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref2]) { results.Ref2s = await FilterReferentials(context.Refs2, processId, ProcessReferentialIdentifier.Ref2).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref3]) { results.Ref3s = await FilterReferentials(context.Refs3, processId, ProcessReferentialIdentifier.Ref3).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref4]) { results.Ref4s = await FilterReferentials(context.Refs4, processId, ProcessReferentialIdentifier.Ref4).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref5]) { results.Ref5s = await FilterReferentials(context.Refs5, processId, ProcessReferentialIdentifier.Ref5).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref6]) { results.Ref6s = await FilterReferentials(context.Refs6, processId, ProcessReferentialIdentifier.Ref6).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref7]) { results.Ref7s = await FilterReferentials(context.Refs7, processId, ProcessReferentialIdentifier.Ref7).ToArrayAsync(); } return(results); }
/// <summary> /// Crée un scénario cible à partir d'un autre scénario, initial ou cible. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="sourceScenario">Le scenario source.</param> /// <param name="natureCode">Le code de la nature.</param> /// <param name="save"><c>true</c> pour sauvegarder le scénario créé.</param> /// <returns> /// Le scénario créé /// </returns> public async Task <Scenario> CreateDerivatedScenario(KsmedEntities context, Scenario sourceScenario, string natureCode, bool save) { Scenario derivatedScenario; // using (var context = ContextFactory.GetNewContext(_securityContext.CurrentUser, _localizationManager)) // { var targetNumber = await context.Scenarios.Where(s => s.ProjectId == sourceScenario.ProjectId && s.NatureCode == natureCode) .CountAsync() + 1; derivatedScenario = await CreateDerivatedScenario(context, sourceScenario, natureCode, save, targetNumber); // } return(derivatedScenario); }
/// <summary> /// Charge les détails des scénarios : /// Actions /// Actions.Reduced /// Actions.Predecessors /// Actions.Solution /// Actions.Ref* /// </summary> /// <param name="context">Le contexte.</param> /// <param name="scenarios">Les scénarios</param> /// <param name="referentialsUse">Les référentiels utilisés, ou <c>null</c> pour les utiliser tous.</param> internal static async Task LoadScenariosDetails(KsmedEntities context, IEnumerable <Scenario> scenarios, IDictionary <ProcessReferentialIdentifier, bool> referentialsUse) { IEnumerable <int> scId = scenarios.Select(s => s.ScenarioId); KAction[] actions = await context.KActions .Include(nameof(KAction.Predecessors)) .Include(nameof(KAction.Reduced)) .Include(nameof(KAction.LinkedProcess)) .Include(nameof(KAction.Thumbnail)) .Where(a => scId.Contains(a.ScenarioId)) .ToArrayAsync(); Solution[] solutions = await context.Solutions.Where(s => scId.Contains(s.ScenarioId)).ToArrayAsync(); await LoadActionsReferentials(context, actions, referentialsUse); }
/// <summary> /// Charge tous les référentiels projets du projet. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="projectId">L'ide du projet.</param> /// <returns>Les référentiels chargés.</returns> private static async Task <Referentials> LoadAllProjectReferentials(KsmedEntities context, int processId) { var dbProjectReferentials = new Referentials { Categories = await context.ActionCategories.OfType <ActionCategory>().Where(r => r.ProcessId == processId).ToArrayAsync(), Equipments = await context.Resources.OfType <Equipment>().Where(r => r.ProcessId == processId).ToArrayAsync(), Operators = await context.Resources.OfType <Operator>().Where(r => r.ProcessId == processId).ToArrayAsync(), Ref1s = await context.Refs1.OfType <Ref1>().Where(r => r.ProcessId == processId).ToArrayAsync(), Ref2s = await context.Refs2.OfType <Ref2>().Where(r => r.ProcessId == processId).ToArrayAsync(), Ref3s = await context.Refs3.OfType <Ref3>().Where(r => r.ProcessId == processId).ToArrayAsync(), Ref4s = await context.Refs4.OfType <Ref4>().Where(r => r.ProcessId == processId).ToArrayAsync(), Ref5s = await context.Refs5.OfType <Ref5>().Where(r => r.ProcessId == processId).ToArrayAsync(), Ref6s = await context.Refs6.OfType <Ref6>().Where(r => r.ProcessId == processId).ToArrayAsync(), Ref7s = await context.Refs7.OfType <Ref7>().Where(r => r.ProcessId == processId).ToArrayAsync(), }; return(dbProjectReferentials); }
/// <summary> /// Charge les scénarios. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <param name="referentialsUsed">Les référentiels utilisés.</param> /// <param name="natureFilter">Le filtre sur les codes de nature de scénario.</param> /// <returns>Les scénarios.</returns> private static async Task <Scenario[]> LoadScenarios(KsmedEntities context, int projectId, IDictionary <ProcessReferentialIdentifier, bool> referentialsUsed, GetDataScenarioNatures natureFilter) { Scenario[] scenarios; ObjectQuery <Scenario> query = context.Scenarios.Include(nameof(Scenario.State)); switch (natureFilter) { case GetDataScenarioNatures.InitialAndTarget: scenarios = await query .Where(s => s.ProjectId == projectId && (s.NatureCode == KnownScenarioNatures.Initial || s.NatureCode == KnownScenarioNatures.Target)) .ToArrayAsync(); break; case GetDataScenarioNatures.Realized: scenarios = await query .Where(s => s.ProjectId == projectId && s.NatureCode == KnownScenarioNatures.Realized) .ToArrayAsync(); break; case GetDataScenarioNatures.All: scenarios = await query .Where(s => s.ProjectId == projectId) .ToArrayAsync(); break; default: throw new ArgumentOutOfRangeException(); } await Queries.LoadScenariosDetails(context, scenarios, referentialsUsed); return(scenarios); }
/// <summary> /// Sauvegarde les actions spécifiées. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="allScenarios">Tous les scénarios liés.</param> /// <param name="updatedScenario">Le scénario qui a été mis à jour.</param> /// <param name="recursive"><c>true</c> pour appliquer les changements récursivement sur les scénarios dérivés.</param> public async Task <Scenario> SaveAcquireData(KsmedEntities context, Scenario[] allScenarios, Scenario updatedScenario, bool recursive) { try { // Don't insert a thumbnail that already exists var actionsWithNewThumbnail = updatedScenario.Actions.Where(_ => (_.IsMarkedAsAdded && _.Thumbnail != null) || (_.IsMarkedAsModified && _.ChangeTracker.ModifiedValues.ContainsKey(nameof(KAction.Thumbnail)) && _.Thumbnail != null)); foreach (var action in actionsWithNewThumbnail) { CloudFile thumbnail = updatedScenario.Actions.Where(_ => _.Thumbnail != null && _.ActionId != action.ActionId).Select(_ => _.Thumbnail).FirstOrDefault(_ => _.Hash == action.ThumbnailHash); if (thumbnail == null) { thumbnail = await context.CloudFiles.SingleOrDefaultAsync(_ => _.Hash == action.Thumbnail.Hash); } if (thumbnail != null) { action.Thumbnail = thumbnail; } } KAction[] actionsToDelete; IList <KAction> actionsWithOriginal; if (recursive) { ActionsRecursiveUpdate.UpdateActions(context, updatedScenario, allScenarios, out actionsToDelete, out actionsWithOriginal); } else { actionsWithOriginal = null; actionsToDelete = updatedScenario.Actions.Where(a => a.IsMarkedAsDeleted).ToArray(); updatedScenario.CriticalPathIDuration = ActionsTimingsMoveManagement.GetInternalCriticalPathDuration(updatedScenario); } // Consolider les solutions vides EnsureEmptySolutionExists(updatedScenario); UdpateSolutionsApprovedState(updatedScenario); // Update InheritedAction if original will be deleted var actionIdsToDelete = actionsToDelete.Select(_ => _.ActionId).ToList(); var inheritedActions = await context.KActions .Where(_ => _.OriginalActionId != null && actionIdsToDelete.Contains(_.OriginalActionId.Value)) .ToListAsync(); foreach (var inheritedAction in inheritedActions) { inheritedAction.OriginalActionId = null; context.KActions.ApplyChanges(inheritedAction); } KAction[] allActions = allScenarios .SelectMany(s => s.Actions) .Where(a => a.IsNotMarkedAsUnchanged) .ToArray(); foreach (KAction action in allActions) { if (!action.IsReduced) { ApplyNewReduced(action, KnownActionCategoryTypes.I); } context.KActions.ApplyChanges(action); context.KActionsReduced.ApplyChanges(action.Reduced); } if (actionsWithOriginal != null) { foreach (KAction action in actionsWithOriginal) { SetActionsOriginalReference(context, action); } } foreach (Scenario scenario in allScenarios.Where(s => s.IsNotMarkedAsUnchanged)) { context.Scenarios.ApplyChanges(scenario); } context.Scenarios.ApplyChanges(updatedScenario); foreach (KAction action in actionsToDelete) { action.Predecessors.Clear(); action.Successors.Clear(); action.MarkAsDeleted(); // Ne pas appeler ApplyChanges car les self tracking le gèrent mal (plantage lors de la sauvegarde) // Ajouter l'action au contexte si elle n'y est pas attachée if (!context.ObjectStateManager.TryGetObjectStateEntry(action, out ObjectStateEntry entry)) { context.AddObject(KsmedEntities.KActionsEntitySetName, action); context.ObjectStateManager.ChangeObjectState(action, EntityState.Deleted); } else { context.KActions.DeleteObject(action); } } // Vérifier que tout est correct if (recursive) { ActionsTimingsMoveManagement.DebugCheckAllWBS(allScenarios.Where(s => s.IsNotMarkedAsUnchanged)); } await context.SaveChangesAsync(); return(updatedScenario); } catch (Exception ex) { TraceManager.TraceError(ex, $"Error while saving scenario {updatedScenario.ScenarioId}"); throw; } }
/// <summary> /// Crée un scénario cible à partir d'un autre scénario, initial ou cible. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="sourceScenario">Le scenario source.</param> /// <param name="natureCode">Le code de la nature.</param> /// <param name="save"><c>true</c> pour sauvegarder le scénario créé.</param> /// <param name="targetNumber">Le numéro cible.</param> /// <returns> /// Le scénario créé /// </returns> public static async Task <Scenario> CreateDerivatedScenario(KsmedEntities context, Scenario sourceScenario, string natureCode, bool save, int targetNumber) { // Charger les données du scénario source var newScenario = new Scenario(); ActionCloneBehavior cloneBehavior; if (sourceScenario.NatureCode == KnownScenarioNatures.Initial && natureCode == KnownScenarioNatures.Target) { cloneBehavior = ActionCloneBehavior.InitialToTarget; } else if (sourceScenario.NatureCode == KnownScenarioNatures.Target && natureCode == KnownScenarioNatures.Target) { cloneBehavior = ActionCloneBehavior.TargetToTarget; } else if (sourceScenario.NatureCode == KnownScenarioNatures.Target && natureCode == KnownScenarioNatures.Realized) { cloneBehavior = ActionCloneBehavior.TargetToRealized; } else if (sourceScenario.NatureCode == KnownScenarioNatures.Realized && natureCode == KnownScenarioNatures.Initial) { cloneBehavior = ActionCloneBehavior.RealizedToNewInitial; } else if (sourceScenario.NatureCode == KnownScenarioNatures.Target && natureCode == KnownScenarioNatures.Initial) { cloneBehavior = ActionCloneBehavior.TargetToNewInitial; } else if (sourceScenario.NatureCode == KnownScenarioNatures.Initial && natureCode == KnownScenarioNatures.Initial) { cloneBehavior = ActionCloneBehavior.InitialToNewInitial; } else { throw new InvalidOperationException("Conversion impossible pour ces scénarios"); } switch (natureCode) { case KnownScenarioNatures.Target: newScenario.Label = LocalizationManager.GetString("Business_AnalyzeService_TargetScenarioLabel") + " " + targetNumber; break; case KnownScenarioNatures.Realized: newScenario.Label = LocalizationManager.GetString("Business_AnalyzeService_ValidationScenarioLabel"); break; case KnownScenarioNatures.Initial: newScenario.Label = LocalizationManager.GetString("Business_AnalyzeService_InitialScenarioLabel"); break; default: throw new ArgumentOutOfRangeException(nameof(natureCode)); } newScenario.StateCode = KnownScenarioStates.Draft; newScenario.NatureCode = natureCode; if (cloneBehavior != ActionCloneBehavior.RealizedToNewInitial && cloneBehavior != ActionCloneBehavior.TargetToNewInitial && cloneBehavior != ActionCloneBehavior.InitialToNewInitial) { newScenario.ProjectId = sourceScenario.ProjectId; newScenario.Original = sourceScenario; newScenario.OriginalScenarioId = sourceScenario.ScenarioId; } newScenario.IsShownInSummary = true; newScenario.CriticalPathIDuration = sourceScenario.CriticalPathIDuration; string[] scenarioLAbels = await EnsureCanShowScenarioInSummary(newScenario, true); // Copier toutes les actions foreach (var action in sourceScenario.Actions.ToArray()) { var newAction = CloneAction(action, cloneBehavior); newAction.OriginalActionId = action.ActionId; newAction.Original = action; if (newAction.Reduced != null) { newAction.Reduced.OriginalBuildDuration = action.BuildDuration; } // S'il s'agit d'un scénario validé, utiliser les temps process en tant que temps vidéo if (cloneBehavior == ActionCloneBehavior.TargetToRealized) { newAction.Start = newAction.BuildStart; newAction.Finish = newAction.BuildFinish; } newScenario.Actions.Add(newAction); } SharedScenarioActionsOperations.EnsureEmptySolutionExists(newScenario); SharedScenarioActionsOperations.UdpateSolutionsApprovedState(newScenario); // Copier les liens prédécesseurs successeurs foreach (var action in sourceScenario.Actions.ToArray()) { var newAction = newScenario.Actions.FirstOrDefault(a => a.OriginalActionId == action.ActionId); if (newAction != null) { foreach (var predecessor in action.Predecessors) { var newPredecessor = newScenario.Actions.FirstOrDefault(a => a.OriginalActionId == predecessor.ActionId); if (newPredecessor != null) { newAction.Predecessors.Add(newPredecessor); } } } } //Suppression des actions avec durée = 0 if (cloneBehavior == ActionCloneBehavior.TargetToRealized || cloneBehavior == ActionCloneBehavior.TargetToTarget) { ActionsRecursiveUpdate.RemoveEmptyDurationActionsAndGroupsFromNewScenario(newScenario); } if (cloneBehavior != ActionCloneBehavior.TargetToRealized && // ToDelete ne s'applique pas aux scenarios validés cloneBehavior != ActionCloneBehavior.InitialToNewInitial && // ToDelete ne s'applique pas aux scenarios initiaux cloneBehavior != ActionCloneBehavior.TargetToNewInitial && // ToDelete ne s'applique pas aux scenarios initiaux cloneBehavior != ActionCloneBehavior.RealizedToNewInitial) // ToDelete ne s'applique pas aux scenarios initiaux { foreach (var newAction in newScenario.Actions) { // Si la category associée est dite "à supprimer", modifier la tache optimisée à "à supprimer" if (newAction.Category != null && newAction.Category.ActionTypeCode == KnownActionCategoryTypes.S) { SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.S); } } } if (save) { context.Scenarios.ApplyChanges(newScenario); await context.SaveChangesAsync(); } ActionsTimingsMoveManagement.FixPredecessorsSuccessorsTimings(newScenario.Actions.ToArray(), false); ActionsTimingsMoveManagement.UpdateVideoGroupsTiming(newScenario.Actions.ToArray()); ActionsTimingsMoveManagement.UpdateBuildGroupsTiming(newScenario.Actions.ToArray()); newScenario.CriticalPathIDuration = ActionsTimingsMoveManagement.GetInternalCriticalPathDuration(newScenario); // Supprimer les liens vers les originaux car dans un autre projet if (cloneBehavior == ActionCloneBehavior.RealizedToNewInitial || cloneBehavior == ActionCloneBehavior.TargetToNewInitial || cloneBehavior == ActionCloneBehavior.InitialToNewInitial) { foreach (var action in newScenario.Actions) { action.Original = null; action.OriginalActionId = null; } newScenario.Original = null; newScenario.OriginalScenarioId = null; } return(newScenario); }
/// <summary> /// Importe le projet spécifié. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="import">Le projet exporté.</param> /// <param name="mergeReferentials"><c>true</c> pour fusionner les référentiels.</param> /// <param name="videosDirectory">Le dossier où se situent les vidéos.</param> /// <returns>Le projet créé.</returns> private async Task <Project> ImportProject(KsmedEntities context, ProjectImport import, bool mergeReferentials, string videosDirectory) { // Projet var p = import.ExportedProject.Project; p.ProjectId = default(int); MarkAsAdded(p); // Ajouter l'utilisateur courant en tant qu'analyste créateur var owner = await context.Users.FirstAsync(u => !u.IsDeleted && u.Username == _securityContext.CurrentUser.Username); p.Process.Owner = owner; p.Process.UserRoleProcesses.Add(new UserRoleProcess() { User = owner, RoleCode = KnownRoles.Analyst, }); // Videos foreach (var video in p.Process.Videos) { if (video.DefaultResourceId.HasValue && video.DefaultResource == null) { // Bug présent dans certains exports de la version 2.5.0.0. Supprimer le lien vers la ressource par défaut. video.DefaultResourceId = null; } video.VideoId = default(int); MarkAsAdded(video); video.FilePath = IOHelper.ChangeDirectory(video.FilePath, videosDirectory); } var referentialsToRemap = new Dictionary <IActionReferential, IActionReferential>(); if (!mergeReferentials) { // Référentiels process foreach (var refe in import.ExportedProject.ReferentialsProject) { MarkAsAdded(refe); } // Référentiels standard foreach (var refe in import.ExportedProject.ReferentialsStandard) { var refProject = ReferentialsFactory.CopyToNewProject(refe); // Associer au process refProject.Process = p.Process; referentialsToRemap[refe] = refProject; } } else { // Référentiels process foreach (var refe in import.ExportedProject.ReferentialsProject) { // Ajouter au tableau de remap s'il y a une correspondance. if (import.ProjectReferentialsMergeCandidates.ContainsKey(refe)) { referentialsToRemap[refe] = import.ProjectReferentialsMergeCandidates[refe]; } else { MarkAsAdded(refe); } } // Référentiels standard foreach (var refe in import.ExportedProject.ReferentialsStandard) { if (import.StandardReferentialsMergeCandidates.ContainsKey(refe)) { referentialsToRemap[refe] = import.StandardReferentialsMergeCandidates[refe]; } else { var refProject = ReferentialsFactory.CopyToNewProject(refe); // Associer au process refProject.Process = p.Process; referentialsToRemap[refe] = refProject; } } } // Scénarios foreach (var scenario in p.Scenarios.Where(s => s.OriginalScenarioId.HasValue)) { // Remapper l'original scenario.Original = p.Scenarios.Single(s => s.ScenarioId == scenario.OriginalScenarioId); } foreach (var scenario in p.Scenarios) { foreach (var action in scenario.Actions.Where(a => a.OriginalActionId.HasValue)) { // Remapper l'original action.Original = p.Scenarios.SelectMany(s => s.Actions).Single(a => a.ActionId == action.OriginalActionId); } } foreach (var scenario in p.Scenarios) { scenario.ScenarioId = default(int); MarkAsAdded(scenario); // Supprimer le WebPublicationGuid scenario.WebPublicationGuid = null; // Actions foreach (var action in scenario.Actions) { action.ActionId = default(int); MarkAsAdded(action); // Actions réduites if (action.IsReduced) { MarkAsAdded(action.Reduced); } } } // Remapper les référentiels du projet, des actions et des vidéos foreach (var oldReferential in referentialsToRemap.Keys) { ReferentialsHelper.UpdateReferentialReferences(p, oldReferential, referentialsToRemap[oldReferential]); } foreach (var scenario in p.Scenarios) { if (scenario.Original != null) { context.Scenarios.ApplyChanges(scenario); ObjectContextExt.SetRelationShipReferenceValue(context, scenario, scenario.Original, s => s.OriginalScenarioId); foreach (var action in scenario.Actions) { if (action.Original != null) { context.KActions.ApplyChanges(action); ObjectContextExt.SetRelationShipReferenceValue(context, action, action.Original, a => a.OriginalActionId); } } } } var resources = p.Scenarios.SelectMany(s => s.Actions).Select(a => a.Resource).Distinct().ToArray(); context.Projects.ApplyChanges(p); if (mergeReferentials) { ServicesDiagnosticsDebug.CheckNotInContext(context, referentialsToRemap.Keys); ServicesDiagnosticsDebug.CheckObjectStateManagerState(context, EntityState.Unchanged, referentialsToRemap.Values); } ServicesDiagnosticsDebug.CheckReferentialsState(); await context.SaveChangesAsync(); return(p); }
/// <summary> /// Charge toutes les propriétés de navigation des référentiels des actions spécifiées. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="actions">les actions.</param> internal static void LoadAllReferentials(KsmedEntities context, IEnumerable <KAction> actions) { Dictionary <int, ActionCategory> categories = new Dictionary <int, ActionCategory>(); Dictionary <int, Skill> skills = new Dictionary <int, Skill>(); Dictionary <int, Resource> resources = new Dictionary <int, Resource>(); Dictionary <int, Ref1> ref1 = new Dictionary <int, Ref1>(); Dictionary <int, Ref2> ref2 = new Dictionary <int, Ref2>(); Dictionary <int, Ref3> ref3 = new Dictionary <int, Ref3>(); Dictionary <int, Ref4> ref4 = new Dictionary <int, Ref4>(); Dictionary <int, Ref5> ref5 = new Dictionary <int, Ref5>(); Dictionary <int, Ref6> ref6 = new Dictionary <int, Ref6>(); Dictionary <int, Ref7> ref7 = new Dictionary <int, Ref7>(); foreach (KAction action in actions) { // Catégorie if (action.CategoryId.HasValue) { if (categories.ContainsKey(action.CategoryId.Value)) { action.Category = categories[action.CategoryId.Value]; } else { context.LoadProperty(action, a => a.Category); categories[action.CategoryId.Value] = action.Category; } } // Compétence if (action.SkillId.HasValue) { if (skills.ContainsKey(action.SkillId.Value)) { action.Skill = skills[action.SkillId.Value]; } else { context.LoadProperty(action, a => a.Skill); skills[action.SkillId.Value] = action.Skill; } } // Ressource if (action.ResourceId != null) { if (resources.ContainsKey(action.ResourceId.Value)) { action.Resource = resources[action.ResourceId.Value]; } else { context.LoadProperty(action, a => a.Resource); resources[action.ResourceId.Value] = action.Resource; } } // Ref1 if (action.Ref1.Count > 0) { foreach (Ref1Action actionLink in action.Ref1) { if (ref1.ContainsKey(actionLink.RefId)) { actionLink.Ref1 = ref1[actionLink.RefId]; } else { context.LoadProperty(actionLink, a => a.Ref1); ref1[actionLink.RefId] = actionLink.Ref1; } } } // Ref2 if (action.Ref2.Count > 0) { foreach (Ref2Action actionLink in action.Ref2) { if (ref2.ContainsKey(actionLink.RefId)) { actionLink.Ref2 = ref2[actionLink.RefId]; } else { context.LoadProperty(actionLink, a => a.Ref2); ref2[actionLink.RefId] = actionLink.Ref2; } } } // Ref3 if (action.Ref3.Count > 0) { foreach (Ref3Action actionLink in action.Ref3) { if (ref3.ContainsKey(actionLink.RefId)) { actionLink.Ref3 = ref3[actionLink.RefId]; } else { context.LoadProperty(actionLink, a => a.Ref3); ref3[actionLink.RefId] = actionLink.Ref3; } } } // Ref4 if (action.Ref4.Count > 0) { foreach (Ref4Action actionLink in action.Ref4) { if (ref4.ContainsKey(actionLink.RefId)) { actionLink.Ref4 = ref4[actionLink.RefId]; } else { context.LoadProperty(actionLink, a => a.Ref4); ref4[actionLink.RefId] = actionLink.Ref4; } } } // Ref5 if (action.Ref5.Count > 0) { foreach (Ref5Action actionLink in action.Ref5) { if (ref5.ContainsKey(actionLink.RefId)) { actionLink.Ref5 = ref5[actionLink.RefId]; } else { context.LoadProperty(actionLink, a => a.Ref5); ref5[actionLink.RefId] = actionLink.Ref5; } } } // Ref6 if (action.Ref6.Count > 0) { foreach (Ref6Action actionLink in action.Ref6) { if (ref6.ContainsKey(actionLink.RefId)) { actionLink.Ref6 = ref6[actionLink.RefId]; } else { context.LoadProperty(actionLink, a => a.Ref6); ref6[actionLink.RefId] = actionLink.Ref6; } } } // Ref7 if (action.Ref7.Count > 0) { foreach (Ref7Action actionLink in action.Ref7) { if (ref7.ContainsKey(actionLink.RefId)) { actionLink.Ref7 = ref7[actionLink.RefId]; } else { context.LoadProperty(actionLink, a => a.Ref7); ref7[actionLink.RefId] = actionLink.Ref7; } } } } }
/// <summary> /// Sauvegarde les actions spécifiées. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="allScenarios">Tous les scénarios liés.</param> /// <param name="updatedScenario">Le scénario qui a été mis à jour.</param> /// <param name="recursive"><c>true</c> pour appliquer les changements récursivement sur les scénarios dérivés.</param> public static Task SaveAcquireData(KsmedEntities context, Scenario[] allScenarios, Scenario updatedScenario, bool recursive) { KAction[] actionsToDelete; IList <KAction> actionsWithOriginal; if (recursive) { ActionsRecursiveUpdate.UpdateActions(context, updatedScenario, allScenarios, out actionsToDelete, out actionsWithOriginal); } else { actionsWithOriginal = null; actionsToDelete = updatedScenario.Actions.Where(a => a.IsMarkedAsDeleted).ToArray(); updatedScenario.CriticalPathIDuration = ActionsTimingsMoveManagement.GetInternalCriticalPathDuration(updatedScenario); } // Consolider les solutions vides EnsureEmptySolutionExists(updatedScenario); UdpateSolutionsApprovedState(updatedScenario); KAction[] allActions = allScenarios .SelectMany(s => s.Actions) .Where(a => a.IsNotMarkedAsUnchanged) .ToArray(); foreach (KAction action in allActions) { if (!action.IsReduced) { ApplyNewReduced(action, KnownActionCategoryTypes.I); } context.KActions.ApplyChanges(action); context.KActionsReduced.ApplyChanges(action.Reduced); } if (actionsWithOriginal != null) { foreach (KAction action in actionsWithOriginal) { SetActionsOriginalReference(context, action); } } foreach (Scenario scenario in allScenarios.Where(s => s.IsNotMarkedAsUnchanged)) { context.Scenarios.ApplyChanges(scenario); } context.Scenarios.ApplyChanges(updatedScenario); foreach (KAction action in actionsToDelete) { action.Predecessors.Clear(); action.Successors.Clear(); action.MarkAsDeleted(); // Ne pas appeler ApplyChanges car les self tracking le gèrent mal (plantage lors de la sauvegarde) // Ajouter l'action au contexte si elle n'y est pas attachée if (!context.ObjectStateManager.TryGetObjectStateEntry(action, out ObjectStateEntry entry)) { context.AddObject(KsmedEntities.KActionsEntitySetName, action); context.ObjectStateManager.ChangeObjectState(action, EntityState.Deleted); } else { context.KActions.DeleteObject(action); } } // Vérifier que tout est correct if (recursive) { ActionsTimingsMoveManagement.DebugCheckAllWBS(allScenarios.Where(s => s.IsNotMarkedAsUnchanged)); } return(context.SaveChangesAsync()); }
/// <summary> /// Sauvegarde le scénario spécifié. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="allScenarios">Tous les scénarios liés.</param> /// <param name="recursive"><c>true</c> pour appliquer les changements récursivement sur les scénarios dérivés.</param> public static Task SaveBuildScenario(KsmedEntities context, Scenario[] allScenarios, Scenario updatedScenario, bool recursive) { // Consolider les solutions string[] distinctSolutionsLabels = updatedScenario.Actions .Where(a => a.IsReduced && !string.IsNullOrWhiteSpace(a.Reduced.Solution)) .Select(a => a.Reduced.Solution) .Distinct() .ToArray(); // Ajouter les nouvelles solutions foreach (string solutionLabel in distinctSolutionsLabels) { if (!updatedScenario.Solutions.Any(s => s.SolutionDescription == solutionLabel)) { // Créer une nouvelle solution Solution solution = new Solution() { SolutionDescription = solutionLabel, }; updatedScenario.Solutions.Add(solution); } } EnsureEmptySolutionExists(updatedScenario); // Supprimer les anciennes solutions Solution[] allSolutions = updatedScenario.Solutions.Where(s => !s.IsEmpty).ToArray(); foreach (Solution sol in allSolutions) { if (!distinctSolutionsLabels.Contains(sol.SolutionDescription)) { sol.MarkAsDeleted(); updatedScenario.Solutions.Remove(sol); } } // Copier le temps original foreach (KActionReduced reduced in updatedScenario.Actions .Where(a => a.IsReduced) .Select(a => a.Reduced) .Where(r => r.OriginalBuildDuration == default(long))) { reduced.OriginalBuildDuration = reduced.Action.BuildDuration; } // Appliquer l'état Approved UdpateSolutionsApprovedState(updatedScenario); ActionsRecursiveUpdate.UpdateActions(context, updatedScenario, allScenarios, out KAction[] actionsToDelete, out IList <KAction> actionsWithOriginal); KAction[] allActions = allScenarios .SelectMany(s => s.Actions) .Where(a => a.IsNotMarkedAsUnchanged || (a.IsReduced && a.Reduced.IsNotMarkedAsUnchanged)) .ToArray(); foreach (KAction action in allActions) { context.KActions.ApplyChanges(action); if (action.IsReduced) { context.KActionsReduced.ApplyChanges(action.Reduced); } } foreach (KAction action in actionsWithOriginal) { SetActionsOriginalReference(context, action); } foreach (Scenario scenario in allScenarios.Where(s => s.IsNotMarkedAsUnchanged)) { context.Scenarios.ApplyChanges(scenario); } foreach (Solution solution in updatedScenario.Solutions) { context.Solutions.ApplyChanges(solution); } // Vérifier que tout est correct ActionsTimingsMoveManagement.DebugCheckAllWBS(allScenarios.Where(s => s.IsNotMarkedAsUnchanged)); return(context.SaveChangesAsync()); }
/// <summary> /// Charge les liens Référentiels - Actions des actions spécifiées. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="actions">Les actions.</param> /// <param name="referentialsUse">Les référentiels utilisés, ou <c>null</c> pour les utiliser tous.</param> internal static async Task LoadActionsReferentials(KsmedEntities context, IEnumerable <KAction> actions, IDictionary <ProcessReferentialIdentifier, bool> referentialsUse) { int[] actionIds = actions.Select(a => a.ActionId).ToArray(); bool isNull = referentialsUse == null; if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref1]) { await context.Ref1Actions .Include(nameof(Ref1Action.Ref1)) .Include($"{nameof(Ref1Action.Ref1)}.{nameof(Ref1.CloudFile)}") .Where(r => actionIds.Contains(r.ActionId)).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref2]) { await context.Ref2Actions .Include(nameof(Ref2Action.Ref2)) .Include($"{nameof(Ref2Action.Ref2)}.{nameof(Ref2.CloudFile)}") .Where(r => actionIds.Contains(r.ActionId)).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref3]) { await context.Ref3Actions .Include(nameof(Ref3Action.Ref3)) .Include($"{nameof(Ref3Action.Ref3)}.{nameof(Ref3.CloudFile)}") .Where(r => actionIds.Contains(r.ActionId)).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref4]) { await context.Ref4Actions .Include(nameof(Ref4Action.Ref4)) .Include($"{nameof(Ref4Action.Ref4)}.{nameof(Ref4.CloudFile)}") .Where(r => actionIds.Contains(r.ActionId)).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref5]) { await context.Ref5Actions .Include(nameof(Ref5Action.Ref5)) .Include($"{nameof(Ref5Action.Ref5)}.{nameof(Ref5.CloudFile)}") .Where(r => actionIds.Contains(r.ActionId)).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref6]) { await context.Ref6Actions .Include(nameof(Ref6Action.Ref6)) .Include($"{nameof(Ref6Action.Ref6)}.{nameof(Ref6.CloudFile)}") .Where(r => actionIds.Contains(r.ActionId)).ToArrayAsync(); } if (isNull || referentialsUse[ProcessReferentialIdentifier.Ref7]) { await context.Ref7Actions .Include(nameof(Ref7Action.Ref7)) .Include($"{nameof(Ref7Action.Ref7)}.{nameof(Ref7.CloudFile)}") .Where(r => actionIds.Contains(r.ActionId)).ToArrayAsync(); } }
/// <summary> /// Permet de charger les ressources utilisées dans le process. /// </summary> /// <param name="context">Le contexte.</param> /// <param name="processId">L'identifiant du process.</param> /// <returns>La requête</returns> internal static IQueryable <Resource> FilterResources(KsmedEntities context, int processId) { return(context.Resources.OfType <Equipment>().Where(e => (e.ProcessId == null || e.ProcessId == processId) && !e.IsDeleted).Cast <Resource>().Union( context.Resources.OfType <Operator>().Where(o => (o.ProcessId == null || o.ProcessId == processId) && !o.IsDeleted).Cast <Resource>())); }
/// <summary> /// Obtient les données pour l'écran Acquérir. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="projectId">L'identifiant du projet.</param> /// <param name="natureFilter">Le filtre sur les codes de nature de scénario.</param> /// <returns> /// Les données /// </returns> public static async Task <AcquireData> GetAcquireData(KsmedEntities context, int projectId, GetDataScenarioNatures natureFilter) { IDictionary <ProcessReferentialIdentifier, bool> referentialsUsed = await GetReferentialsUse(context, projectId); int processId = (await context.Projects.SingleAsync(p => p.ProjectId == projectId)).ProcessId; AcquireData data = new AcquireData { Categories = await Queries.FilterReferentials(context.ActionCategories, processId, ProcessReferentialIdentifier.Category).ToArrayAsync(), Skills = await Queries.FilterReferentials(context.Skills, processId, ProcessReferentialIdentifier.Skill).ToArrayAsync(), Resources = await Queries.FilterResources(context, processId).ToArrayAsync(), Videos = await context.Projects .Include(nameof(Project.Process)) .Include($"{nameof(Project.Process)}.{nameof(Procedure.Videos)}") .Where(p => p.ProjectId == projectId) .SelectMany(p => p.Process.Videos) .OrderBy(v => v.CameraName).OrderBy(v => v.DefaultResourceId).OrderBy(v => v.ResourceView).OrderBy(v => v.ShootingDate) .ToArrayAsync() }; if (referentialsUsed[ProcessReferentialIdentifier.Ref1]) { data.Ref1s = await Queries.FilterReferentials(context.Refs1, processId, ProcessReferentialIdentifier.Ref1).ToArrayAsync(); } if (referentialsUsed[ProcessReferentialIdentifier.Ref2]) { data.Ref2s = await Queries.FilterReferentials(context.Refs2, processId, ProcessReferentialIdentifier.Ref2).ToArrayAsync(); } if (referentialsUsed[ProcessReferentialIdentifier.Ref3]) { data.Ref3s = await Queries.FilterReferentials(context.Refs3, processId, ProcessReferentialIdentifier.Ref3).ToArrayAsync(); } if (referentialsUsed[ProcessReferentialIdentifier.Ref4]) { data.Ref4s = await Queries.FilterReferentials(context.Refs4, processId, ProcessReferentialIdentifier.Ref4).ToArrayAsync(); } if (referentialsUsed[ProcessReferentialIdentifier.Ref5]) { data.Ref5s = await Queries.FilterReferentials(context.Refs5, processId, ProcessReferentialIdentifier.Ref5).ToArrayAsync(); } if (referentialsUsed[ProcessReferentialIdentifier.Ref6]) { data.Ref6s = await Queries.FilterReferentials(context.Refs6, processId, ProcessReferentialIdentifier.Ref6).ToArrayAsync(); } if (referentialsUsed[ProcessReferentialIdentifier.Ref7]) { data.Ref7s = await Queries.FilterReferentials(context.Refs7, processId, ProcessReferentialIdentifier.Ref7).ToArrayAsync(); } Project project = await context.Projects.Include(nameof(Project.Process)).SingleAsync(p => p.ProjectId == projectId); data.CustomFieldsLabels = GetCustomFieldsLabels(project); Scenario[] scenarios = null; Scenario[] scenariosUsedForMapping = null; if (natureFilter == GetDataScenarioNatures.InitialAndTarget) { // Il y a tout ce qu'il faut pour faire le mapping dans les scenarii chargés scenariosUsedForMapping = await LoadScenarios(context, projectId, referentialsUsed, GetDataScenarioNatures.InitialAndTarget); scenarios = scenariosUsedForMapping; } else if (natureFilter == GetDataScenarioNatures.Realized) { // Il faut charger au moins les scenarii cibles également scenariosUsedForMapping = await LoadScenarios(context, projectId, referentialsUsed, GetDataScenarioNatures.All); scenarios = scenariosUsedForMapping.Where(scenario => scenario.NatureCode == KnownScenarioNatures.Realized).ToArray(); } else { // Le cas all à priori, on considère de toute façon qu'il s'agit du cas par défaut scenariosUsedForMapping = await LoadScenarios(context, projectId, referentialsUsed, natureFilter); scenarios = scenariosUsedForMapping; } ScenarioActionHierarchyHelper.MapScenariosActionsOriginals(scenariosUsedForMapping); data.Scenarios = scenarios; return(data); }
/// <summary> /// Met à jour les actions récursivement sur les scénarios dérivés de celui spécifié. /// </summary> /// <param name="context">Le contexte EF.</param> /// <param name="sourceScenario">Le scénario source.</param> /// <param name="allScenarios">Tous les scénarios qui peuvent être impactés.</param> /// <param name="actionsToRemove">Les actions à supprimer manuellement.</param> internal static void UpdateActions(KsmedEntities context, Scenario sourceScenario, Scenario[] allScenarios, out KAction[] actionsToRemove, out IList <KAction> actionsWithOriginal) { var derivedScenarios = ScenarioActionHierarchyHelper.GetDerivedScenarios(sourceScenario, allScenarios); var actions = GetActionsSortedWBS(sourceScenario); actionsWithOriginal = new List <KAction>(); foreach (var scenario in derivedScenarios) { // Mettre à jour IsGroup foreach (var action in scenario.Actions) { action.IsGroup = WBSHelper.HasChildren(action, scenario.Actions); } } foreach (var originalAction in actions) { // J'enlève le IsMArkedAsModified car les 2 références sont la sauvegarde des actions depuis la construction et depuis l'optimisation // Or depuis la construction, en modification, le bout de code cidessous est déjà appelé // Et depuis l'optimisation, il n'y a pas de changement de temps video if (originalAction.IsMarkedAsAdded /*|| originalAction.IsMarkedAsModified*/) { var originalValues = originalAction.ChangeTracker.OriginalValues; var modifiedValues = originalAction.ChangeTracker.ModifiedValues; if (originalAction.IsMarkedAsAdded || modifiedValues.ContainsKey(ActionsTimingsMoveManagement.KActionStartPropertyName) || modifiedValues.ContainsKey(ActionsTimingsMoveManagement.KActionFinishPropertyName)) { // Vérifier si le temps vidéo a changé ActionsTimingsMoveManagement.GetOrignalModifiedVideoDurations(originalAction, out long originalDuration, out long modifiedDuration); bool hasVideoDurationChanged = originalDuration != modifiedDuration; // Si c'est une tâche créée et non dupliquée, le buildDuration est à 0, donc on doit le mettre à jour //Sinon, si c'est une tâche dupliquée, on le laisse tel quel. if (originalAction.BuildDuration == 0) { var paceRating = originalAction.Resource != null ? originalAction.Resource.PaceRating : 1d; originalAction.BuildDuration = Convert.ToInt64(modifiedDuration * paceRating); } } } if (originalAction.IsMarkedAsAdded) { // Si l'action est une action nouvelle dans un scénario cible, définir automatiquement la partie réduite if (sourceScenario.NatureCode == KnownScenarioNatures.Target && originalAction.Reduced == null) { SharedScenarioActionsOperations.ApplyNewReduced(originalAction); } var originalActionKey = context.CreateEntityKey(KsmedEntities.KActionsEntitySetName, originalAction); var parentOriginalAction = WBSHelper.GetParent(originalAction, actions); foreach (var derivedScenario in derivedScenarios) { var derivedActions = GetActionsSortedWBS(derivedScenario); // Rechercher le parent dans le scénario dérivé var parentDerivedAction = ScenarioActionHierarchyHelper.GetDerivedAction(parentOriginalAction, derivedScenario); // Cloner l'action originale var newAction = ScenarioCloneManager.CloneAction(originalAction, ActionCloneBehavior.Cascade); // Assigner l'original var originalActionForCurrentDerivedScenario = derivedScenario.Original == sourceScenario ? originalAction : ScenarioActionHierarchyHelper.GetDerivedAction(originalAction, derivedScenario.Original); newAction.Original = originalActionForCurrentDerivedScenario; actionsWithOriginal.Add(newAction); // Insérer l'action clonée dans le scénario dérivé ActionsTimingsMoveManagement.InsertUpdateWBS( derivedActions, newAction, parentDerivedAction, WBSHelper.GetParts(originalAction.WBS).Last(), (a, wbs) => EnsureTracking(a)); // Rafraichir les actions derivedScenario.Actions.Add(newAction); derivedActions = GetActionsSortedWBS(derivedScenario); // Ajouter les mêmes prédécesseurs et successeurs foreach (var originalPredecessor in originalAction.Predecessors) { var derivedPredecessor = ScenarioActionHierarchyHelper.GetDerivedAction(originalPredecessor, derivedScenario); if (derivedPredecessor != null) { EnsureTracking(derivedPredecessor); ActionsTimingsMoveManagement.AddPredecessor(derivedActions, newAction, derivedPredecessor); } } foreach (var originalSuccessor in originalAction.Successors) { var derivedSuccessor = ScenarioActionHierarchyHelper.GetDerivedAction(originalSuccessor, derivedScenario); if (derivedSuccessor != null) { EnsureTracking(derivedSuccessor); ActionsTimingsMoveManagement.AddPredecessor(derivedActions, derivedSuccessor, newAction); } } EnsureTracking(derivedScenario); SharedScenarioActionsOperations.EnsureEmptySolutionExists(derivedScenario); SharedScenarioActionsOperations.UdpateSolutionsApprovedState(derivedScenario); ActionsTimingsMoveManagement.DebugCheckAllWBS(derivedActions); } } else if (originalAction.IsMarkedAsModified) { var originalValues = originalAction.ChangeTracker.OriginalValues; var modifiedValues = originalAction.ChangeTracker.ModifiedValues; var propertiesToCopyValues = new Dictionary <string, object>(); foreach (var propertyName in _kActionPropertyNamesToCopy) { if (modifiedValues.ContainsKey(propertyName)) { propertiesToCopyValues[propertyName] = modifiedValues[propertyName]; } } // Vérifier si les reduced doit être impactés également ActionsTimingsMoveManagement.GetOrignalModifiedBuildDurations(originalAction, out long originalDuration, out long modifiedDuration); bool hasBuildDurationChanged = originalDuration != modifiedDuration; foreach (var derivedScenario in derivedScenarios) { var derivedAction = ScenarioActionHierarchyHelper.GetDerivedAction(originalAction, derivedScenario); if (derivedAction != null) { EnsureTracking(derivedAction); foreach (var kvp in propertiesToCopyValues) { derivedAction.SetPropertyValue(kvp.Key, kvp.Value); } if (hasBuildDurationChanged) { if (derivedAction.IsReduced) { // Modifier l'original duration et recalculer le temps final en fonction du gain EnsureTracking(derivedAction.Reduced); derivedAction.Reduced.OriginalBuildDuration = modifiedDuration; ActionsTimingsMoveManagement.UpdateTimingsFromReducedReduction(derivedAction); } else { // Simplement recopier la durée derivedAction.BuildDuration = modifiedDuration; } } } } } } var toRemove = new List <KAction>(); // Gérer les actions supprimées // EF gérant mal l'ordre des suppressions, ça créer une ConstraintException sur la FK OriginalActionId // Malheureusement un CascadeDelete est impossible puisque la FK est sur un même table if (sourceScenario.ChangeTracker.ObjectsRemovedFromCollectionProperties.ContainsKey("Actions")) { var removedActions = sourceScenario.ChangeTracker.ObjectsRemovedFromCollectionProperties["Actions"].ToArray(); foreach (KAction originalAction in removedActions) { EnsureTracking(originalAction); toRemove.Add(originalAction); originalAction.MarkAsUnchanged(); foreach (var derivedScenario in derivedScenarios) { var derivedAction = ScenarioActionHierarchyHelper.GetDerivedAction(originalAction, derivedScenario); if (derivedAction != null) { var derivedActions = GetActionsSortedWBS(derivedScenario); // Mettre à jour les WBS des autres actions ActionsTimingsMoveManagement.DeleteUpdateWBS(derivedActions, derivedAction, (a, wbs) => EnsureTracking(a)); EnsureTracking(derivedAction); toRemove.Add(derivedAction); } } } // Il faut maintenant trier les actions à supprimer pour que la suppression se fasse dans le bon ordre toRemove.Reverse(); actionsToRemove = toRemove.ToArray(); } else { actionsToRemove = new KAction[] { } }; sourceScenario.CriticalPathIDuration = ActionsTimingsMoveManagement.GetInternalCriticalPathDuration(sourceScenario); foreach (var scenario in derivedScenarios) { EnsureTracking(scenario); ActionsTimingsMoveManagement.FixPredecessorsSuccessorsTimings(scenario.Actions.ToArray(), false); ActionsTimingsMoveManagement.UpdateVideoGroupsTiming(scenario.Actions.ToArray()); ActionsTimingsMoveManagement.UpdateBuildGroupsTiming(scenario.Actions.ToArray()); scenario.CriticalPathIDuration = ActionsTimingsMoveManagement.GetInternalCriticalPathDuration(scenario); } }