/// <summary> /// Автоматическая выдача прав на проектные документы. /// </summary> public virtual void GrantAccessRightsToProjectDocuments() { var startDate = Calendar.Now; var lastStartDate = Docflow.PublicFunctions.Module.GetLastAgentRunDate(Constants.Module.LastProjectDocumentRightsUpdateDate); // Измененные документы. Logger.DebugFormat("GrantAccessRightsToProjectDocuments: Start get changed projects documents."); var queue = new List <Sungero.Projects.Structures.ProjectDocumentRightsQueueItem.ProxyQueueItem>(); var changedDocumentIds = Docflow.OfficialDocuments.GetAll(d => d.Modified >= lastStartDate && d.Modified <= startDate && (d.Project != null || (Docflow.Addendums.Is(d) && d.LeadingDocument.Project != null))) .Select(d => d.Id); foreach (var documentId in changedDocumentIds) { var document = Docflow.OfficialDocuments.GetAll(d => d.Id == documentId).FirstOrDefault(); if (document == null) { continue; } var project = Docflow.PublicFunctions.OfficialDocument.GetProject(document); if (project == null) { continue; } queue.AddRange(Functions.Module.CreateAccessRightsProjectDocumentQueueItemWithAddendum(document.Id, project.Id)); } // Измененные проекты. Logger.DebugFormat("GrantAccessRightsToProjectDocuments: Start get changed projects members documents."); var changedProjectsQueueItems = ProjectMemberRightsQueueItems.GetAll().ToList(); foreach (var memberQueueItem in changedProjectsQueueItems) { var project = Projects.GetAll(p => p.Id == memberQueueItem.ProjectId).FirstOrDefault(); if (project == null) { continue; } var allProjects = ModuleFunctions.GetProjectAndSubProjects(project).Cast <Docflow.IProjectBase>().ToList(); var changedMembersDocuments = Docflow.OfficialDocuments.GetAll(d => allProjects.Contains(d.Project)); foreach (var document in changedMembersDocuments) { queue.AddRange(Functions.Module.CreateAccessRightsProjectDocumentQueueItemWithAddendum(document.Id, project.Id)); } } var table = ProjectDocumentRightsQueueItems.Info.DBTableName; var ids = Sungero.Domain.IdentifierGenerator.GenerateIdentifiers(table, queue.Count).ToList(); for (int i = 0; i < queue.Count; i++) { queue[i].Id = ids[i]; } Docflow.PublicFunctions.Module.WriteStructuresToTable(table, queue); Logger.DebugFormat("GrantAccessRightsToProjectDocuments: Added to queue {0} documents.", queue.Count); if (changedProjectsQueueItems.Any()) { Docflow.PublicFunctions.Module.FastDeleteQueueItems(changedProjectsQueueItems.Select(q => q.Id).ToList()); } // Обновить дату запуска агента в базе. Docflow.PublicFunctions.Module.UpdateLastAgentRunDate(Constants.Module.LastProjectDocumentRightsUpdateDate, startDate); // Выдать права на документы. var step = 5; var error = 0; var isEmpty = false; for (int i = 0; i < 10000; i = i + step) { // Если элементов больше нет - заканчиваем. if (isEmpty) { break; } var result = Transactions.Execute( () => { Logger.DebugFormat("GrantAccessRightsToProjectDocuments: Start process queue from {0}.", i); // Т.к. в конце транзакции элементы удаляются, в Take берем просто N новых элементов. var queueItemPart = ProjectDocumentRightsQueueItems.GetAll().Skip(error).Take(step).ToList(); if (!queueItemPart.Any()) { // Завершаем транзакцию, если больше нечего обрабатывать. isEmpty = true; return; } var accessRightsGranted = queueItemPart .Where(q => Functions.Module.AddDocumentToFolder(q) && Functions.Module.GrantRightsToProjectDocuments(q)) .ToList(); if (accessRightsGranted.Any()) { Docflow.PublicFunctions.Module.FastDeleteQueueItems(accessRightsGranted.Select(a => a.Id).ToList()); } error += queueItemPart.Count - accessRightsGranted.Count; }); if (!result) { error += step; } } }
public override void Saving(Sungero.Domain.SavingEventArgs e) { base.Saving(e); #region абота с папками // Создание папки проекта. if (_obj.Folder == null) { var folder = Folders.Create(); folder.Name = _obj.ShortName; folder.Items.Add(_obj); _obj.Folder = folder; } // Вложение папки проекта в корневую папку или папку ведущего проекта. var projectsFolder = Folders.GetAll().Single(f => f.Uid == Constants.Module.ProjectFolders.ProjectFolderUid); if (_obj.State.Properties.LeadingProject.IsChanged) { // Удаление из папки предыдущего проекта. var leading = _obj.State.Properties.LeadingProject.OriginalValue; if (leading != null && !Equals(leading, _obj.LeadingProject) && leading.Folder != null && leading.Folder.Items.Contains(_obj.Folder)) { leading.Folder.Items.Remove(_obj.Folder); } } if (_obj.LeadingProject == null) { if (projectsFolder != null && !projectsFolder.Items.Contains(_obj.Folder) && _obj.Stage != Stage.Completed) { projectsFolder.Items.Add(_obj.Folder); } } else { // Удаление из корневой папки. if (projectsFolder != null) { projectsFolder.Items.Remove(_obj.Folder); } // Добавление в папку ведущего проекта. if (_obj.LeadingProject.Folder != null && !_obj.LeadingProject.Folder.Items.Contains(_obj.Folder)) { _obj.LeadingProject.Folder.Items.Add(_obj.Folder); } } #endregion #region Переименование групп, папок if (_obj.State.Properties.ShortName.IsChanged) { _obj.Folder.Name = _obj.ShortName; } #endregion #region Перенос в папку Архив и обратно if (_obj.State.Properties.Stage.OriginalValue != _obj.Stage && _obj.LeadingProject == null) { var rootProjectFolder = Folders.GetAll().Single(f => f.Uid == Constants.Module.ProjectFolders.ProjectFolderUid); var archiveFolder = Folders.GetAll().Single(f => f.Uid == Constants.Module.ProjectFolders.ProjectArhiveFolderUid); var projectFolder = _obj.Folder; if (_obj.Stage == Stage.Completed) { archiveFolder.Items.Add(projectFolder); rootProjectFolder.Items.Remove(projectFolder); } else { rootProjectFolder.Items.Add(projectFolder); archiveFolder.Items.Remove(projectFolder); } } #endregion #region Создание и обновление папок проекта Functions.Project.UpdateClassifier(_obj); #endregion #region Очередь выдачи прав участнику var properties = _obj.State.Properties; var needAddToQueue = false; if (properties.Manager.IsChanged && properties.Manager.OriginalValue != _obj.Manager) { needAddToQueue = true; } if (properties.Administrator.IsChanged && _obj.Administrator != null && properties.Administrator.OriginalValue != _obj.Administrator) { needAddToQueue = true; } if (properties.InternalCustomer.IsChanged && _obj.InternalCustomer != null && properties.InternalCustomer.OriginalValue != _obj.InternalCustomer) { needAddToQueue = true; } if (properties.TeamMembers.IsChanged && _obj.TeamMembers.Any()) { needAddToQueue = true; } if (_obj.State.Properties.LeadingProject.IsChanged) { var originalLeadProject = properties.LeadingProject.OriginalValue; var leadProject = _obj.LeadingProject; if (leadProject != null && leadProject != originalLeadProject) { needAddToQueue = true; } } if (needAddToQueue) { Logger.DebugFormat("CreateProjectMemberRightsQueueItem: project {0}", _obj.Id); var queueItem = ProjectMemberRightsQueueItems.Create(); queueItem.ProjectId = _obj.Id; queueItem.Save(); // Добавить признак того, что нужно запустить ФП Автоматическое назначение прав на документы. e.Params.Add(Docflow.PublicConstants.OfficialDocument.GrantAccessRightsToProjectDocument, true); } #endregion #region Выдача прав РП и администратору var recipients = new List <IRecipient>() { _obj.Manager }; if (_obj.Administrator != null) { recipients.Add(_obj.Administrator); } var folders = new List <IFolder>(); if (_obj.Folder != null) { folders.Add(_obj.Folder); } folders.AddRange(_obj.Classifier.Where(c => c.Folder != null).Select(f => f.Folder).ToList()); foreach (var recipient in recipients) { foreach (var folder in folders) { if (!folder.AccessRights.IsGrantedDirectly(DefaultAccessRightsTypes.FullAccess, recipient) && (Locks.GetLockInfo(folder) == null || !Locks.GetLockInfo(folder).IsLockedByOther)) { folder.AccessRights.Grant(recipient, DefaultAccessRightsTypes.FullAccess); } } if (!_obj.AccessRights.IsGrantedDirectly(DefaultAccessRightsTypes.FullAccess, recipient) && Equals(recipient, _obj.Manager)) { _obj.AccessRights.Grant(recipient, DefaultAccessRightsTypes.FullAccess); } if (!Functions.Module.CheckGrantedRights(_obj, recipient, DefaultAccessRightsTypes.Change) && Equals(recipient, _obj.Administrator)) { _obj.AccessRights.Grant(recipient, DefaultAccessRightsTypes.Change); } } #endregion }