/// <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());
        }
Example #2
0
        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);
        }
Example #3
0
        public virtual IQueryable <Sungero.Workflow.IAssignmentBase> OnApprovalDataQuery(IQueryable <Sungero.Workflow.IAssignmentBase> query)
        {
            // Фильтр по типу.
            var typeFilterEnabled     = _filter != null && (_filter.RuleBased || _filter.Free);
            var showRuleBasedApproval = !typeFilterEnabled || _filter.RuleBased;
            var showFreeApproval      = !typeFilterEnabled || _filter.Free;
            var result = query
                         .Where(a => showRuleBasedApproval && (ApprovalAssignments.Is(a) || ApprovalManagerAssignments.Is(a)) ||
                                showFreeApproval && FreeApprovalAssignments.Is(a));

            // Запрос непрочитанных без фильтра.
            if (_filter == null)
            {
                return(RecordManagement.PublicFunctions.Module.ApplyCommonSubfolderFilters(result));
            }

            // Фильтры по статусу, замещению и периоду.
            result = RecordManagement.PublicFunctions.Module.ApplyCommonSubfolderFilters(result, _filter.InProcess,
                                                                                         _filter.Last30Days, _filter.Last90Days, _filter.Last180Days, false);

            return(result);
        }
        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);
        }
Example #5
0
        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());
        }