예제 #1
0
        public virtual void GetMyTodayAssignmentsChartValue(Sungero.Domain.GetWidgetPieChartValueEventArgs e)
        {
            AccessRights.AllowRead(
                () =>
            {
                var assignments = Workflow.Assignments.GetAll();

                var overdue = Functions.Module.GetMyAssignments(assignments, _parameters.Substitution, Constants.Module.TodayAssignments.OverdueToday).Count();
                if (overdue != 0)
                {
                    e.Chart.AddValue(Constants.Module.TodayAssignments.OverdueToday, Resources.WidgetMTAOverdue, overdue, Colors.Charts.Red);
                }

                var deadline = Functions.Module.GetMyAssignments(assignments, _parameters.Substitution, Constants.Module.TodayAssignments.DeadlineToday).Count();
                if (deadline != 0)
                {
                    e.Chart.AddValue(Constants.Module.TodayAssignments.DeadlineToday, Resources.WidgetMTADeadline, deadline, Colors.Charts.Color1);
                }

                var after = Functions.Module.GetMyFutureAssignments(assignments, _parameters.Substitution);
                if (after != null && after.Count != 0)
                {
                    e.Chart.AddValue(after.ConstantName, after.Resource, after.Count, Colors.Charts.Color6);
                }

                var completed = Functions.Module.GetMyAssignments(assignments, _parameters.Substitution, Constants.Module.TodayAssignments.CompletedToday).Count();
                if (completed != 0)
                {
                    e.Chart.AddValue(Constants.Module.TodayAssignments.CompletedToday, Resources.WidgetMTACompleted, completed, Colors.Charts.Green);
                }
            });
        }
예제 #2
0
        public static string GetMeetingNameIgnoreAccessRights(int id)
        {
            var name = string.Empty;

            AccessRights.AllowRead(
                () =>
            {
                var meeting = Meetings.GetAll(m => Equals(m.Id, id)).FirstOrDefault();
                if (!string.IsNullOrWhiteSpace(meeting.Name))
                {
                    name += string.Format(" {0} \"{1}\"", Agendas.Resources.For, meeting.Name);
                }
            });
            return(name);
        }
    public bool AnyApprovalTasksWithCurrentDocument()
    {
        var anyTasks = false;

        AccessRights.AllowRead(
            () =>
        {
            anyTasks = finex.Entity.Tasks.GetAll()
                       .Where(t => t.Status == finex.Entity.Task.Status.InProcess ||
                              t.Status == finex.Entity.Task.Status.Suspended)
                       .Where(t => t.AttachmentDetails.Any(att => att.AttachmentId == _obj.Id))
                       .Any();
        });

        return(anyTasks);
    }
예제 #4
0
        public static string GetMeetingNameWithDateIgnoreAccessRights(int id)
        {
            var name = string.Empty;

            AccessRights.AllowRead(
                () =>
            {
                var meeting = Meetings.GetAll(m => Equals(m.Id, id)).FirstOrDefault();
                if (meeting.DateTime != null)
                {
                    name += Docflow.OfficialDocuments.Resources.DateFrom + meeting.DateTime.Value.ToString("d");
                }
                name += GetMeetingNameIgnoreAccessRights(id);
            });
            return(name);
        }
예제 #5
0
        public virtual bool IsRegistrationNumberUnique(IOfficialDocument document, string registrationNumber, int index,
                                                       DateTime registrationDate, string departmentCode, string businessUnitCode,
                                                       string caseFileIndex, string docKindCode, string counterpartyCode, int leadDocumentId)
        {
            var checkRegistrationNumberUnique = Functions.OfficialDocument.CheckRegistrationNumberUnique(document);

            // У финансовых документов и договоров явно отключаем требование уникальности рег. номера.
            if (!checkRegistrationNumberUnique)
            {
                return(true);
            }

            var result        = true;
            var leadDoc       = OfficialDocuments.GetAll().FirstOrDefault(x => x.Id == leadDocumentId);
            var leadDocNumber = leadDoc == null ? string.Empty : leadDoc.RegistrationNumber;

            AccessRights.AllowRead(
                () =>
            {
                if (index == 0)
                {
                    // Параметр функции "Искать корректировочный постфикс" = true, если необходимо проверять рег. номер на уникальность.
                    index = Functions.DocumentRegister.GetIndexFromRegistrationNumber(_obj, registrationDate, registrationNumber, departmentCode,
                                                                                      businessUnitCode, caseFileIndex, docKindCode, counterpartyCode, leadDocNumber,
                                                                                      checkRegistrationNumberUnique);
                }

                var equalsIndexes = Functions.DocumentRegister.GetSameNumberDocuments(_obj, document, registrationDate, index).ToList();

                foreach (var equalsIndex in equalsIndexes)
                {
                    // Параметр функции "Искать корректировочный постфикс" = true, если необходимо проверять рег. номер на уникальность.
                    if (Functions.DocumentRegister.IsEqualsRegistrationNumbers(_obj, registrationDate, equalsIndex.RegistrationNumber,
                                                                               departmentCode, businessUnitCode, caseFileIndex, docKindCode, counterpartyCode, leadDocNumber,
                                                                               registrationNumber, checkRegistrationNumberUnique))
                    {
                        result = false;
                    }
                }
            });

            return(result);
        }
        public bool AnyApprovalTasksWithCurrentDocument()
        {
            var anyTasks = false;

            AccessRights.AllowRead(
                () =>
            {
                var docGuid = _obj.GetEntityMetadata().GetOriginal().NameGuid;
                var approvalTaskDocumentGroupGuid = Constants.Module.TaskMainGroup.ApprovalTask;
                anyTasks = ApprovalTasks.GetAll()
                           .Where(t => t.Status == Workflow.Task.Status.InProcess ||
                                  t.Status == Workflow.Task.Status.Suspended)
                           .Where(t => t.AttachmentDetails
                                  .Any(att => att.AttachmentId == _obj.Id && att.EntityTypeGuid == docGuid &&
                                       att.GroupId == approvalTaskDocumentGroupGuid))
                           .Any();
            });

            return(anyTasks);
        }
예제 #7
0
        public virtual void GetTasksCreatingDynamicTasksDynamicChartValue(Sungero.Domain.GetWidgetPlotChartValueEventArgs e)
        {
            var period = _parameters.Period == Widgets.TasksCreatingDynamic.Period.Last90Days ? -90 :
                         (_parameters.Period == Widgets.TasksCreatingDynamic.Period.Last180Days ? -180 : -30);
            var periodEnd    = Sungero.Core.Calendar.Today.EndOfDay();
            var periodBegin  = Sungero.Core.Calendar.Today.AddDays(period).BeginningOfDay();
            var palette      = Functions.Module.GetPlotColorPalette();
            var allEmployees = Employees.GetAll();

            var topSeriesCount = 4;

            Structures.Module.ObjectCreateDynamicCache cachedTasks;

            if (Equals(_parameters.CarriedObjects, Widgets.TasksCreatingDynamic.CarriedObjects.All) && Docflow.PublicFunctions.Module.Remote.IsAdministratorOrAdvisor())
            {
                // Общий кэш для аудиторов и администраторов по всем сотрудникам.
                cachedTasks = Functions.Module.GetCachedTasks(null, allEmployees.Select(x => x.Id).ToList(), _parameters.CarriedObjects);
            }
            else
            {
                // Получение списка сотрудников департамента текущего сотрудника.
                var employees = Functions.Module.FilterWidgetRecipientsBySubstitution(allEmployees,
                                                                                      _parameters.CarriedObjects == Widgets.TasksCreatingDynamic.CarriedObjects.My,
                                                                                      _parameters.CarriedObjects == Widgets.TasksCreatingDynamic.CarriedObjects.MyDepartment)
                                .Select(x => x.Id).ToList();

                cachedTasks = Functions.Module.GetCachedTasks(Users.Current, employees, _parameters.CarriedObjects);
            }

            var tasks = cachedTasks.Points.Where(x => x.Date >= periodBegin).ToList();

            if (!tasks.Any())
            {
                return;
            }

            // Упорядоченный список типов. Т.к. в точках хранится накопительная сумма, значение на последний день будет максимальным, по нему и определяем топ.
            var maxDate     = tasks.Max(x => x.Date);
            var topTypeList = tasks.Where(x => x.Date == maxDate).OrderByDescending(x => x.Count).Select(x => x.TypeDiscriminator).ToList();

            e.Chart.Axis.X.AxisType = AxisType.DateTime;
            e.Chart.Axis.Y.Title    = Resources.WidgetTasksCreatingDynamicYAxisTitle;
            var maxValue = 0;
            var minValue = int.MaxValue;

            // Все типы.
            if (topTypeList.Any())
            {
                var iteratedPeriodBegin = periodBegin;
                var iteratedPeriodEnd   = periodBegin.EndOfDay();
                var serieColor          = palette.FirstOrDefault();
                var serie = e.Chart.AddNewSeries(Resources.WidgetTasksCreatingDynamicSeriesAllTasks, serieColor);

                while (iteratedPeriodEnd <= periodEnd)
                {
                    var count = tasks.Where(x => x.Date == iteratedPeriodEnd.Date).Sum(x => x.Count);
                    if (count > maxValue)
                    {
                        maxValue = count;
                    }

                    serie.AddValue(iteratedPeriodEnd.Date, count);

                    iteratedPeriodBegin = iteratedPeriodBegin.AddDays(1);
                    iteratedPeriodEnd   = iteratedPeriodEnd.AddDays(1);
                }
            }

            // Топовые типы.
            var topTypes = topTypeList.Take(topSeriesCount).ToList();

            foreach (var taskType in topTypes)
            {
                var points = tasks.Where(x => Equals(x.TypeDiscriminator, taskType)).ToList();

                var startPoint = points.OrderBy(x => x.Date).First();
                var startCount = startPoint.Count;
                var startDate  = startPoint.Date;

                // Dmitriev_IA: важно знать позицию, а не сам индекс. Позиция типа задачи в списке всегда на 1 больше, чем индекс.
                var taskTypeIndex = topTypes.FindIndex(t => Equals(t, taskType)) + 1;
                var serieColor    = palette.Skip(taskTypeIndex).FirstOrDefault();

                var iteratedPeriodBegin = periodBegin;
                var iteratedPeriodEnd   = periodBegin.EndOfDay();

                var typeName = string.Empty;

                AccessRights.AllowRead(
                    () =>
                {
                    var task = Workflow.Tasks.GetAll().Where(t => t.TypeDiscriminator.ToString() == taskType).First();
                    typeName = Workflow.SimpleTasks.Is(task) ? Docflow.Resources.SimpleTask : task.Info.LocalizedName;
                });

                var serie = e.Chart.AddNewSeries(typeName, serieColor);

                while (iteratedPeriodEnd <= periodEnd)
                {
                    var count = iteratedPeriodBegin < startDate ? 0 : startCount;
                    var point = points.Where(x => x.Date == iteratedPeriodEnd.Date).FirstOrDefault();

                    if (point != null)
                    {
                        count = point.Count;
                    }

                    serie.AddValue(iteratedPeriodEnd.Date, count);

                    if (count < minValue)
                    {
                        minValue = count;
                    }

                    iteratedPeriodBegin = iteratedPeriodBegin.AddDays(1);
                    iteratedPeriodEnd   = iteratedPeriodEnd.AddDays(1);
                }
            }

            // Прочие типы.
            var top3Types  = topTypeList.Skip(topSeriesCount).ToList();
            var otherTasks = tasks.Where(x => top3Types.Contains(x.TypeDiscriminator)).ToList();

            if (otherTasks.Any())
            {
                var iteratedPeriodBegin = periodBegin;
                var iteratedPeriodEnd   = periodBegin.EndOfDay();
                var serieColor          = palette.Skip(topSeriesCount + 1).FirstOrDefault();
                var serie = e.Chart.AddNewSeries(Resources.WidgetTasksCreatingDynamicSeriesOtherDocuments, serieColor);

                while (iteratedPeriodEnd <= periodEnd)
                {
                    var count = otherTasks.Where(x => x.Date == iteratedPeriodEnd.Date).Sum(x => x.Count);

                    serie.AddValue(iteratedPeriodEnd.Date, count);

                    iteratedPeriodBegin = iteratedPeriodBegin.AddDays(1);
                    iteratedPeriodEnd   = iteratedPeriodEnd.AddDays(1);
                }
            }

            // Dmitriev_IA: Ограничение оси Oy графика
            if (minValue > Math.Round(maxValue * 0.1))
            {
                e.Chart.Axis.Y.MinValue = Math.Round(minValue * 0.95);
            }
            else
            {
                e.Chart.Axis.Y.MinValue = 0;
            }

            e.Chart.Axis.Y.MaxValue = Math.Round(maxValue * 1.05);
        }
        public override void BeforeExecute(Sungero.Reporting.Server.BeforeExecuteEventArgs e)
        {
            if (SkippedNumbersReport.DocumentRegisterId.HasValue)
            {
                SkippedNumbersReport.DocumentRegister = DocumentRegisters.Get(SkippedNumbersReport.DocumentRegisterId.Value);
            }

            SkippedNumbersReport.CurrentDate = Calendar.Now;

            var documentRegister = SkippedNumbersReport.DocumentRegister;

            var documents = Enumerable.Empty <IOfficialDocument>().AsQueryable();

            AccessRights.AllowRead(() =>
                                   { documents = Docflow.OfficialDocuments.GetAll()
                                                 .Where(d => d.DocumentRegister == SkippedNumbersReport.DocumentRegister)
                                                 .Where(d => d.RegistrationState == RegistrationState.Registered || d.RegistrationState == RegistrationState.Reserved); });

            #region Период формирования отчета и разрезы

            var baseDate     = Calendar.UserNow;
            var periodOffset = SkippedNumbersReport.PeriodOffset.HasValue
        ? SkippedNumbersReport.PeriodOffset.Value
        : 0;

            // Признак того, что отчет запущен из диалога регистрации.
            var launchedFromDialog = SkippedNumbersReport.RegistrationDate.HasValue;

            if (launchedFromDialog)
            {
                baseDate = SkippedNumbersReport.RegistrationDate.Value;
                // По умолчанию для отчета из диалога регистрации берем данные за последний месяц.
                SkippedNumbersReport.Period       = Constants.SkippedNumbersReport.Month;
                SkippedNumbersReport.PeriodOffset = 0;
            }

            if (SkippedNumbersReport.Period.Equals(Constants.SkippedNumbersReport.Year))
            {
                SkippedNumbersReport.PeriodBegin = Calendar.BeginningOfYear(baseDate.AddYears(periodOffset));
                SkippedNumbersReport.PeriodEnd   = periodOffset == 0 ? Calendar.EndOfYear(baseDate) :
                                                   Calendar.EndOfYear(baseDate.AddYears(periodOffset));
            }
            if (SkippedNumbersReport.Period.Equals(Constants.SkippedNumbersReport.Quarter))
            {
                SkippedNumbersReport.PeriodBegin = Docflow.PublicFunctions.AccountingDocumentBase.BeginningOfQuarter(baseDate.AddMonths(3 * periodOffset));
                SkippedNumbersReport.PeriodEnd   = periodOffset == 0 ? Docflow.PublicFunctions.AccountingDocumentBase.EndOfQuarter(baseDate) :
                                                   Docflow.PublicFunctions.AccountingDocumentBase.EndOfQuarter(baseDate.AddMonths(3 * periodOffset));
            }
            if (SkippedNumbersReport.Period.Equals(Constants.SkippedNumbersReport.Month))
            {
                SkippedNumbersReport.PeriodBegin = Calendar.BeginningOfMonth(baseDate.AddMonths(periodOffset));
                SkippedNumbersReport.PeriodEnd   = periodOffset == 0 ? Calendar.EndOfMonth(baseDate) :
                                                   Calendar.EndOfMonth(baseDate.AddMonths(periodOffset));
            }
            if (SkippedNumbersReport.Period.Equals(Constants.SkippedNumbersReport.Week))
            {
                SkippedNumbersReport.PeriodBegin = Calendar.BeginningOfWeek(baseDate.AddDays(7 * periodOffset));
                SkippedNumbersReport.PeriodEnd   = periodOffset == 0 ? Calendar.EndOfWeek(baseDate) :
                                                   Calendar.EndOfWeek(baseDate.AddDays(7 * periodOffset));
            }

            // Получить границы периода журнала регистрации.
            var      registrationDate            = launchedFromDialog ? SkippedNumbersReport.RegistrationDate.Value : SkippedNumbersReport.PeriodEnd.Value;
            DateTime?documentRegisterPeriodBegin = Functions.DocumentRegister.GetBeginPeriod(documentRegister, registrationDate);
            DateTime?documentRegisterPeriodEnd   = Functions.DocumentRegister.GetEndPeriod(documentRegister, registrationDate) ?? SkippedNumbersReport.PeriodEnd.Value;

            // Начало расчетного периода.
            var periodBegin = SkippedNumbersReport.PeriodBegin;

            // Если отчет вызван из диалога регистрации взять "месяц назад" от даты регистрации.
            if (launchedFromDialog)
            {
                periodBegin = registrationDate.AddMonths(-1);
            }

            // Если начало указанного периода раньше начала периода журнала, то считать от последнего.
            if (documentRegisterPeriodBegin.HasValue && documentRegisterPeriodBegin > periodBegin)
            {
                periodBegin = documentRegisterPeriodBegin;
            }
            else if (!documentRegisterPeriodBegin.HasValue)
            {
                documentRegisterPeriodBegin = Calendar.SqlMinValue;
            }

            SkippedNumbersReport.PeriodBegin = periodBegin;

            // Конец расчетного периода.
            var periodEnd = launchedFromDialog ? SkippedNumbersReport.RegistrationDate.Value.EndOfDay() : SkippedNumbersReport.PeriodEnd;
            SkippedNumbersReport.PeriodEnd = periodEnd;

            var hasLeadingDocument = SkippedNumbersReport.LeadingDocument != null;
            var hasDepartment      = SkippedNumbersReport.Department != null;
            var hasBusinessUnit    = SkippedNumbersReport.BusinessUnit != null;

            // Отфильтровать документы по разрезам.
            if (hasLeadingDocument)
            {
                documents = documents.Where(d => Equals(d.LeadingDocument, SkippedNumbersReport.LeadingDocument));
            }

            if (hasDepartment)
            {
                documents = documents.Where(d => Equals(d.Department, SkippedNumbersReport.Department));
            }

            if (hasBusinessUnit)
            {
                documents = documents.Where(d => Equals(d.BusinessUnit, SkippedNumbersReport.BusinessUnit));
            }

            #endregion

            #region Генерация формата номера

            var numberFormat = string.Empty;
            foreach (var item in documentRegister.NumberFormatItems.OrderBy(x => x.Number))
            {
                var elementName = string.Empty;
                if (item.Element == DocumentRegisterNumberFormatItems.Element.Number)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatNumber;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.Year2Place || item.Element == DocumentRegisterNumberFormatItems.Element.Year4Place)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatYear;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.Quarter)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatQuarter;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.Month)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatMonth;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.LeadingNumber)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatLeadingNumber;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.Log)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatLog;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.RegistrPlace)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatRegistrPlace;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.CaseFile)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatCaseFile;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.DepartmentCode)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatDepartmentCode;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.BUCode)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatBUCode;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.DocKindCode)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatDocKindCode;
                }
                else if (item.Element == DocumentRegisterNumberFormatItems.Element.CPartyCode)
                {
                    elementName = DocumentRegisters.Resources.NumberFormatCounterpartyCode;
                }

                numberFormat += elementName + item.Separator;
            }
            SkippedNumbersReport.NumberFormat = numberFormat;

            #endregion

            #region Границы индексов в выбранном периоде

            // Получить минимальный индекс по документам в периоде (при ручной регистрации мб нарушение следования индексов).
            var firstDocumentIndex = Functions.DocumentRegister.GetIndex(documents, periodBegin, periodEnd, false);

            // Получить индекс документа из предыдущего периода.
            var previousIndex = 0;
            if (periodBegin != documentRegisterPeriodBegin)
            {
                previousIndex = Functions.DocumentRegister.FilterDocumentsByPeriod(documents, documentRegisterPeriodBegin,
                                                                                   periodBegin.Value.AddDays(-1).EndOfDay())
                                .Where(d => !firstDocumentIndex.HasValue || d.Index < firstDocumentIndex).Select(d => d.Index).OrderByDescending(a => a).FirstOrDefault() ?? 0;
            }

            if (firstDocumentIndex == null)
            {
                firstDocumentIndex = previousIndex + 1;
            }

            var firstIndex = firstDocumentIndex < previousIndex ? firstDocumentIndex : previousIndex + 1;

            // Получить первый индекс документа следующего периода.
            var nextIndex = periodEnd != documentRegisterPeriodEnd?
                            Functions.DocumentRegister.GetIndex(documents, periodEnd.Value.AddDays(1).BeginningOfDay(), documentRegisterPeriodEnd, false) : null;

            // Если в следующем периоде ещё нет документов, то взять текущий индекс журнала.
            var leadingDocumentId = hasLeadingDocument
        ? SkippedNumbersReport.LeadingDocument.Id
        : 0;
            var departmentId = hasDepartment
        ? SkippedNumbersReport.Department.Id
        : 0;
            var businessUnitId = hasBusinessUnit
        ? SkippedNumbersReport.BusinessUnit.Id
        : 0;
            if (nextIndex == null)
            {
                nextIndex = Functions.DocumentRegister.GetCurrentNumber(documentRegister, registrationDate, leadingDocumentId, departmentId, businessUnitId) + 1;
            }

            // Получить индекс по зарегистрированным документам (при ручной регистрации мб нарушение следования индексов).
            var lastDocumentIndex = Functions.DocumentRegister.GetIndex(documents, periodBegin, periodEnd, true) ?? nextIndex - 1;
            var lastIndex         = lastDocumentIndex >= nextIndex ? lastDocumentIndex : nextIndex - 1;

            // Для случая когда нет документов в периоде.
            if (lastIndex < firstIndex)
            {
                lastIndex = firstIndex - 1;
            }

            #endregion

            // Отфильтровать документы по найденным границам индексов и по периоду журнала регистрации.
            // Допускать документы с номером не соответствующим формату (Index = 0).
            documents = documents
                        .Where(d => !documentRegisterPeriodBegin.HasValue || d.RegistrationDate >= documentRegisterPeriodBegin)
                        .Where(d => !documentRegisterPeriodEnd.HasValue || d.RegistrationDate <= documentRegisterPeriodEnd)
                        .Where(l => l.Index >= firstIndex && l.Index <= lastIndex ||
                               (l.Index == 0 && l.RegistrationDate <= SkippedNumbersReport.PeriodEnd && l.RegistrationDate >= SkippedNumbersReport.PeriodBegin));

            // Заполнить маску для гиперссылки.
            if (documents.Count() > 0)
            {
                var link  = Hyperlinks.Get(documents.First());
                var index = link.IndexOf("?type=");
                SkippedNumbersReport.hyperlinkMask = link.Substring(0, index) + "?type=DocGUID&id=DocId";
            }
            else
            {
                SkippedNumbersReport.hyperlinkMask = string.Empty;
            }

            #region Вычислить пропущенные индексы

            // Создать временную таблицу для списка номеров "подряд".
            var skipsTableName = Constants.SkippedNumbersReport.SkipsTableName;
            SkippedNumbersReport.SkipsTableName = skipsTableName;
            var skipedNumberList = new List <string>();
            var skipedNumbers    = new List <Structures.SkippedNumbersReport.SkippedNumber>();
            var reportSessionId  = Guid.NewGuid().ToString();
            SkippedNumbersReport.ReportSessionId = reportSessionId;

            // Заполнить таблицу номеров.
            var month     = documentRegisterPeriodBegin.Value.Month < 10 ? string.Format("0{0}", documentRegisterPeriodBegin.Value.Month) : documentRegisterPeriodBegin.Value.Month.ToString();
            var day       = documentRegisterPeriodBegin.Value.Day < 10 ? string.Format("0{0}", documentRegisterPeriodBegin.Value.Day) : documentRegisterPeriodBegin.Value.Day.ToString();
            var startDate = string.Format("{0}{1}{2}", documentRegisterPeriodBegin.Value.Year, month, day);

            month = documentRegisterPeriodEnd.Value.Month < 10 ? string.Format("0{0}", documentRegisterPeriodEnd.Value.Month) : documentRegisterPeriodEnd.Value.Month.ToString();
            day   = documentRegisterPeriodEnd.Value.Day < 10 ? string.Format("0{0}", documentRegisterPeriodEnd.Value.Day) : documentRegisterPeriodEnd.Value.Day.ToString();
            var endDate = string.Format("{0}{1}{2}", documentRegisterPeriodEnd.Value.Year, month, day);

            var queryText = string.Format(Queries.SkippedNumbersReport.GetSkippedIndexes,
                                          SkippedNumbersReport.DocumentRegister.Id.ToString(),
                                          (firstIndex - 1).ToString(),
                                          (lastIndex + 1).ToString(),
                                          hasBusinessUnit.ToString(),
                                          businessUnitId.ToString(),
                                          hasDepartment.ToString(),
                                          departmentId.ToString(),
                                          hasLeadingDocument.ToString(),
                                          leadingDocumentId.ToString(),
                                          documentRegisterPeriodBegin.HasValue.ToString(),
                                          startDate,
                                          endDate);

            // Получить интервалы пропущеных индексов журнала в периоде.
            // Key - начало интервала, Value - окончиние интервала.
            var skippedIndexIntervals = new Dictionary <int, int>();
            using (var command = SQL.GetCurrentConnection().CreateCommand())
            {
                command.CommandText = queryText;
                var result = command.ExecuteReader();
                while (result.Read())
                {
                    skippedIndexIntervals.Add((int)result[1], (int)result[0]);
                }
                result.Close();
            }

            // Заполнить отчет данными для пропущенных индексов.
            foreach (var interval in skippedIndexIntervals)
            {
                var intervalStart = interval.Key;
                var intervalEnd   = interval.Value;

                // Три и более подряд идущих пропущеных индексов должны быть собраны в одну строку.
                var intervalLength = intervalEnd - intervalStart + 1;
                if (intervalLength >= 3)
                {
                    skipedNumbers.Add(Structures.SkippedNumbersReport.SkippedNumber.Create(Docflow.Reports.Resources.SkippedNumbersReport.NumbersAreSkipped,
                                                                                           string.Format("{0}-{1}", intervalStart.ToString(), intervalEnd.ToString()),
                                                                                           intervalStart,
                                                                                           reportSessionId));
                    skipedNumberList.Add(string.Format("{0}-{1}",
                                                       intervalStart.ToString(),
                                                       intervalEnd.ToString()));

                    continue;
                }

                for (var i = intervalStart; i <= intervalEnd; i++)
                {
                    skipedNumbers.Add(Structures.SkippedNumbersReport.SkippedNumber.Create(Docflow.Reports.Resources.SkippedNumbersReport.NumberIsSkipped,
                                                                                           i.ToString(),
                                                                                           i,
                                                                                           reportSessionId));
                    skipedNumberList.Add(i.ToString());
                }
            }

            #endregion

            Functions.Module.WriteStructuresToTable(skipsTableName, skipedNumbers);

            // Получить 8-10 первых пропущенных номеров строкой. Для остальных указать общее количество.
            var skipedNumberCount       = skipedNumberList.Count;
            var maxDisplayedNumberCount = 10;
            var minHiddenNumberCount    = 3;
            var displayedValuesCount    = skipedNumberCount;
            if (skipedNumberCount >= (maxDisplayedNumberCount + minHiddenNumberCount))
            {
                displayedValuesCount = maxDisplayedNumberCount;
            }
            else if (skipedNumberCount > maxDisplayedNumberCount)
            {
                displayedValuesCount = skipedNumberCount - minHiddenNumberCount;
            }

            SkippedNumbersReport.SkipedNumberList = string.Join(", ", skipedNumberList.ToArray(), 0, displayedValuesCount);
            var hiddenSkipedNumberCount = skipedNumberCount - displayedValuesCount;
            if (hiddenSkipedNumberCount > 0)
            {
                var numberLabel = Functions.Module.GetNumberDeclination(hiddenSkipedNumberCount,
                                                                        Resources.SkippedNumbersReportNumber,
                                                                        Resources.SkippedNumbersReportNumberGenetive,
                                                                        Resources.SkippedNumbersReportNumberPlural);

                SkippedNumbersReport.SkipedNumberList += string.Format(Sungero.Docflow.Reports.Resources.SkippedNumbersReport.And, hiddenSkipedNumberCount, numberLabel);
            }

            // Создать таблицу для доступных пользователю документов.
            var availableDocuments = new List <Structures.SkippedNumbersReport.AvailableDocument>();
            var previousDocDate    = Calendar.SqlMinValue;
            foreach (var document in documents.ToList().OrderBy(x => x.Index))
            {
                var numberOnFormat = document.Index != null && document.Index != 0;
                var canRead        = document.AccessRights.CanRead();
                var inCorrectOrder = (previousDocDate <= document.RegistrationDate || !numberOnFormat) &&
                                     (document.RegistrationDate >= SkippedNumbersReport.PeriodBegin && document.RegistrationDate <= SkippedNumbersReport.PeriodEnd);
                availableDocuments.Add(Structures.SkippedNumbersReport.AvailableDocument.Create(document.Id, numberOnFormat, canRead, inCorrectOrder, reportSessionId));

                if (numberOnFormat && inCorrectOrder)
                {
                    previousDocDate = document.RegistrationDate.Value;
                }
            }

            SkippedNumbersReport.AvailableDocumentsTableName = Constants.SkippedNumbersReport.AvailableDocumentsTableName;
            Functions.Module.WriteStructuresToTable(SkippedNumbersReport.AvailableDocumentsTableName, availableDocuments);
        }