/// <summary> /// Получить согласующих, которые будут реально согласовывать на текущей итерации. /// </summary> /// <returns>Согласующие.</returns> public List <Company.IEmployee> GetCurrentIterationEmployeesWithoutAssignment() { var approvalTask = ApprovalTasks.As(_obj.Task); var performers = ApprovalAssignments.GetAll(x => Equals(x.Task, approvalTask) && x.IterationId == _obj.IterationId && Equals(x.BlockUid, _obj.BlockUid) && x.TaskStartId == _obj.TaskStartId) .Select(x => x.Performer).Distinct().ToList(); return(GetCurrentIterationEmployees(approvalTask, _obj.Stage) .Where(x => !performers.Contains(x)) .ToList()); }
public override void BeforeAbort(Sungero.Workflow.Server.BeforeAbortEventArgs e) { // Если прекращён черновик, прикладную логику по прекращению выполнять не надо. if (_obj.State.Properties.Status.OriginalValue == Workflow.Task.Status.Draft) { return; } var document = _obj.DocumentGroup.OfficialDocuments.First(); var subject = string.Empty; var threadSubject = string.Empty; // Отправить уведомления о прекращении. using (TenantInfo.Culture.SwitchTo()) { threadSubject = ApprovalTasks.Resources.AbortNoticeSubject; subject = string.Format(Sungero.Exchange.Resources.TaskSubjectTemplate, threadSubject, Docflow.PublicFunctions.Module.TrimSpecialSymbols(document.Name)); } var allApprovers = ApprovalAssignments.GetAll(asg => asg.Task == _obj && asg.IsRead.Value).Select(app => app.Performer).ToList(); allApprovers.AddRange(ApprovalManagerAssignments.GetAll(asg => asg.Task == _obj && asg.IsRead.Value).Select(app => app.Performer).ToList()); allApprovers.AddRange(ApprovalSigningAssignments.GetAll(asg => asg.Task == _obj && asg.IsRead.Value).Select(app => app.Performer).ToList()); var author = _obj.Author; var reworkAssignment = Functions.ApprovalTask.GetLastReworkAssignment(_obj); if (reworkAssignment != null) { allApprovers.Add(reworkAssignment.Performer); if (!Equals(_obj.Author, reworkAssignment.Performer)) { allApprovers.Add(_obj.Author); author = reworkAssignment.Performer; } } allApprovers.Remove(Users.Current); if (allApprovers.Any()) { Functions.Module.SendNoticesAsSubtask(subject, allApprovers, _obj, _obj.AbortingReason, author, threadSubject); } // Обновить статус согласования - аннулирован. Functions.ApprovalTask.UpdateApprovalState(_obj, OfficialDocument.InternalApprovalState.Aborted); }
public virtual bool CanForwardTo(Company.IEmployee employee) { var assignments = ApprovalAssignments.GetAll(a => Equals(a.Task, _obj.Task) && Equals(a.TaskStartId, _obj.TaskStartId) && Equals(a.IterationId, _obj.IterationId)); // Если у сотрудника есть хоть одно задание в работе - считаем, что нет смысла дублировать ему задания. // BUG: если assignments материализовать (завернуть ToList), то в задании можно будет переадресовать самому себе, т.к. в BeforeComplete задание считается уже выполненным. var hasInProcess = assignments.Where(a => Equals(a.Status, Status.InProcess) && Equals(a.Performer, employee)).Any(); if (hasInProcess) { return(false); } // При последовательном выполнении сотрудники ещё не получили задания, вычисляем их. var currentStageApprovers = Functions.ApprovalAssignment.GetCurrentIterationEmployeesWithoutAssignment(_obj); if (currentStageApprovers.Contains(employee)) { return(false); } var materialized = assignments.ToList(); // Если у сотрудника нет заданий в работе, проверяем, все ли его задания созданы. foreach (var assignment in materialized) { var added = assignment.ForwardedTo.Count(u => Equals(u, employee)); var created = materialized.Count(a => Equals(a.Performer, employee) && Equals(a.ForwardedFrom, assignment)); if (added != created) { return(false); } } return(true); }
public virtual List <IRecipient> GetStageRecipients(IApprovalTask task, List <Sungero.CoreEntities.IRecipient> additionalApprovers) { var recipients = new List <IRecipient>(); if (_obj.StageType == StageType.Approvers || _obj.StageType == StageType.Notice || _obj.StageType == StageType.SimpleAgr || _obj.StageType == StageType.CheckReturn) { // Сотрудники/группы. if (_obj.Recipients.Any()) { recipients.AddRange(_obj.Recipients .Where(rec => rec.Recipient != null) .Select(rec => rec.Recipient) .ToList()); } } // Роли согласования. if (_obj.ApprovalRoles.Any()) { recipients.AddRange(_obj.ApprovalRoles .Where(r => r.ApprovalRole != null && r.ApprovalRole.Type != Docflow.ApprovalRoleBase.Type.Approvers) .Select(r => Functions.ApprovalRoleBase.GetRolePerformer(r.ApprovalRole, task)) .Where(r => r != null) .ToList()); } // Обработать роль "Согласующие" отдельно, так как она множественная. if (_obj.ApprovalRoles.Any(r => r.ApprovalRole.Type == Docflow.ApprovalRoleBase.Type.Approvers)) { var role = _obj.ApprovalRoles.Where(r => r.ApprovalRole != null && r.ApprovalRole.Type == Docflow.ApprovalRoleBase.Type.Approvers) .Select(r => ApprovalRoles.As(r.ApprovalRole)) .Where(r => r != null) .FirstOrDefault(); recipients.AddRange(Functions.ApprovalRole.GetApproversRolePerformers(role, task, additionalApprovers)); } // Для типа этапа "Контроль возврата" добавить исполнителем инициатора, если других исполнителей нет. if (_obj.StageType == StageType.CheckReturn) { var performers = Functions.Module.GetEmployeesFromRecipients(recipients); if (!performers.Any()) { recipients.Add(task.Author); } } // Для согласующих дополнительно нужны те, кому переадресовали (или кого добавили в процессе согласования). if (_obj.StageType == StageType.Approvers) { var assignments = ApprovalAssignments.GetAll() .Where(a => Equals(a.Task, task) && Equals(a.TaskStartId, task.StartId) && Equals(a.Stage, _obj)) .ToList(); foreach (var assignment in assignments) { if (assignment.ForwardedTo == null) { continue; } recipients.AddRange(assignment.ForwardedTo); } } // Согласование с доп. согласующими. if (_obj.StageType == StageType.Approvers && _obj.AllowAdditionalApprovers == true) { if (additionalApprovers != null) { recipients.AddRange(additionalApprovers); } else { recipients.AddRange(task.AddApproversExpanded .Where(a => a.Approver != null) .Select(a => a.Approver) .ToList()); } if (task.Status != Docflow.ApprovalTask.Status.Draft) { var assignments = ApprovalAssignments.GetAll() .Where(a => Equals(a.Task, task) && Equals(a.TaskStartId, task.StartId) && Equals(a.Stage, _obj) && Equals(a.Status, Workflow.Assignment.Status.InProcess)) .ToList(); foreach (var assignment in assignments) { if (assignment.ForwardedTo == null) { continue; } recipients.AddRange(assignment.ForwardedTo); } } } return(recipients.Distinct().ToList()); }