Почему в 1С:УТ 11.5 дублируются документы внутреннего товародвижения в списке, если у пользователя есть ограничения по складу?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При работе в системе 1С:Управление Торговлей 11.5 пользователи могут столкнуться с неожиданным поведением: в журнале "Внутренние документы" некоторые документы, особенно связанные с товародвижением, отображаются в списке дважды. При этом попытки очистки кэша или анализа ключей реестра документов не выявляют явных причин для такого дублирования на уровне данных. Это создает путаницу и затрудняет работу, особенно если у пользователя установлены ограничения прав доступа по складам.

Рассмотрим подробно, почему возникает такая ситуация и как ее эффективно разрешить. Мы вместе выясним корень проблемы, проанализируем типовую реализацию динамического списка и предложим практические шаги по устранению дубликатов.

Анализируем проявление проблемы: что на самом деле представляют собой "дубли"?

Первое, что мы должны сделать, это внимательно рассмотреть, как именно проявляются эти "дубликаты" в списке. При попытке провалиться в любую из дублирующихся строк, мы обнаруживаем, что это один и тот же документ. Однако, при этом, в разных строках списка отображается разная информация, например, по складам:

  1. В одной строке мы видим документ как "перемещение со склада-отправителя".
  2. В другой строке этот же документ отображается как "перемещение на склад-получатель".

Это ключевая подсказка. Это не истинные дубликаты документа, а скорее разные его представления в списке. В системе 1С:УТ 11.5 это часто связано с особенностями хранения данных в регистрах сведений, используемых для формирования динамических списков.

Исследуем данные: роль регистра сведений "РеестрДокументов" и поля "ДополнительнаяЗапись"

Далее мы углубимся в структуру данных, которая лежит в основе динамического списка. В конфигурации 1С:УТ 11.5 для формирования списков документов часто используется РегистрСведений.РеестрДокументов. Этот регистр является своего рода "виртуальным" представлением документов, агрегирующим ключевую информацию из них.

При детальном рассмотрении записей в РегистрСведений.РеестрДокументов для таких документов перемещения, мы обнаруживаем, что для каждого документа действительно создаются две записи:

  1. Одна запись помечена как основная.
  2. Вторая запись помечена как "дополнительная запись".

Для идентификации этих записей в регистре существует специальное логическое поле ДополнительнаяЗапись. Оно предназначено для поддержки различных способов отображения одного и того же документа в разных контекстах или для разных пользователей. Например, для документов перемещения товаров оно позволяет хранить информацию как с точки зрения склада-отправителя, так и с точки зрения склада-получателя. Это обеспечивает гибкость в формировании отчетов и списков, позволяя пользователям видеть документ в соответствии с их ролью и правами доступа.

Таким образом, наша проблема не в дублировании самих документов или их основных данных, а в том, что динамический список отображает обе записи из регистра РеестрДокументов — и основную, и дополнительную.

Анализируем типовой запрос динамического списка

Теперь рассмотрим, как формируется динамический список "Внутренние документы". Обычно, запросы для таких списков довольно просты, выбирая данные непосредственно из регистра РеестрДокументов. Давайте посмотрим на типичный запрос, используемый для формирования списка:


ВЫБРАТЬ
    РеестрДокументовПереопределяемый.Ссылка КАК Ссылка,
    РеестрДокументовПереопределяемый.Проведен КАК Проведен,
    РеестрДокументовПереопределяемый.ПометкаУдаления КАК ПометкаУдаления,
    РеестрДокументовПереопределяемый.НомерДокументаИБ КАК Номер,
    РеестрДокументовПереопределяемый.ДатаДокументаИБ КАК Дата,
    РеестрДокументовПереопределяемый.Организация КАК Организация,
    РеестрДокументовПереопределяемый.Подразделение КАК Подразделение,
    РеестрДокументовПереопределяемый.МестоХранения КАК МестоХранения,
    ВЫРАЗИТЬ(РеестрДокументовПереопределяемый.МестоХранения.Ключ КАК Справочник.Склады) КАК Склад,
    РеестрДокументовПереопределяемый.Ответственный КАК Менеджер,
    РеестрДокументовПереопределяемый.ХозяйственнаяОперация КАК ХозяйственнаяОперация,
    РеестрДокументовПереопределяемый.Статус КАК Статус,
    РеестрДокументовПереопределяемый.Дополнительно КАК Дополнительно,
    РеестрДокументовПереопределяемый.Комментарий КАК Комментарий,
    РеестрДокументовПереопределяемый.НомерПервичногоДокумента КАК НомерВходящегоДокумента,
    РеестрДокументовПереопределяемый.ДатаПервичногоДокумента КАК ДатаВходящегоДокумента,
    ВЫБОР
        КОГДА РеестрДокументовПереопределяемый.Проведен
            ТОГДА 0
        КОГДА РеестрДокументовПереопределяемый.ПометкаУдаления
            ТОГДА 1
        ИНАЧЕ 2
    КОНЕЦ КАК НестандартнаяКартинка,
    РеестрДокументовПереопределяемый.ДополнительнаяЗапись КАК ДополнительнаяЗапись,
    РеестрДокументовПереопределяемый.ТипСсылки КАК ТипСсылки,
    &СтатусПроверки КАК СтатусПроверки,
    &ИндикаторПроверки КАК ИндикаторПроверки,
    ТИПЗНАЧЕНИЯ(РеестрДокументовПереопределяемый.Ссылка) КАК ТипЗначения,
    РеестрДокументовПереопределяемый.СторноИсправление КАК СторноИсправление,
    ВЫБОР
        КОГДА НЕ РеестрДокументовПереопределяемый.СторноИсправление
            ТОГДА НЕОПРЕДЕЛЕНО
        ИНАЧЕ РеестрДокументовПереопределяемый.СторнируемыйДокумент
    КОНЕЦ КАК СторнируемыйИсправляемыйДокумент,
    NULL КАК СостояниеОригиналаПервичногоДокумента,
    ИСТИНА КАК ОбщееСостояние,
    0 КАК СостояниеОригиналПолучен
{ГДЕ
    РеестрДокументовПереопределяемый.Ссылка.* КАК Ссылка,
    РеестрДокументовПереопределяемый.МестоХранения.* КАК МестоХранения,
    ВЫРАЗИТЬ(РеестрДокументовПереопределяемый.МестоХранения.Ключ КАК Справочник.Склады).* КАК Склад,
    РеестрДокументовПереопределяемый.Организация.* КАК Организация,
    РеестрДокументовПереопределяемый.ДатаДокументаИБ КАК Дата,
    РеестрДокументовПереопределяемый.НомерДокументаИБ КАК Номер,
    РеестрДокументовПереопределяемый.Статус КАК Статус,
    РеестрДокументовПереопределяемый.ХозяйственнаяОперация КАК ХозяйственнаяОперация,
    РеестрДокументовПереопределяемый.Подразделение.* КАК Подразделение,
    РеестрДокументовПереопределяемый.Ответственный.* КАК Ответственный,
    РеестрДокументовПереопределяемый.Дополнительно КАК Дополнительно,
    РеестрДокументовПереопределяемый.Комментарий КАК Комментарий,
    РеестрДокументовПереопределяемый.Проведен КАК Проведен,
    РеестрДокументовПереопределяемый.ПометкаУдаления КАК ПометкаУдаления,
    ((РеестрДокументовПереопределяемый.ДатаДокументаИБ >= &НачалоПериода
    ИЛИ &НачалоПериода = ДАТАВРЕМЯ(1, 1, 1))
    И (РеестрДокументовПереопределяемый.ДатаДокументаИБ <= &КонецПериода
    ИЛИ &КонецПериода = ДАТАВРЕМЯ(1, 1, 1)))}
ИЗ
    РегистрСведений.РеестрДокументов КАК РеестрДокументовПереопределяемый

В этом запросе мы видим, что поле РеестрДокументовПереопределяемый.ДополнительнаяЗапись выбирается, но в секции {ГДЕ} нет явного отбора по этому полю. Это означает, что без дополнительных условий список будет выводить все записи из регистра, включая и основные, и дополнительные.

Выявляем причину дублирования: почему отбор по "ДополнительнаяЗапись" не срабатывает?

Типовые конфигурации 1С обычно предусматривают механизмы, которые скрывают дополнительные записи от большинства пользователей, оставляя только основные. Мы должны рассмотреть модуль формы списка документов, чтобы найти этот механизм. Часто такой отбор устанавливается в процедуре УстановитьОтборыДинамическихСписков() или аналогичной.

Находим следующий фрагмент кода в модуле формы списка:


Если Не ИспользуетсяОграничениеПоСкладу Тогда
    ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(СписокДокументыВнутреннегоТовародвижения, "ДополнительнаяЗапись",
        Ложь, ВидСравненияКомпоновкиДанных.Равно, Неопределено, Не ЗначениеЗаполнено(Склад));
КонецЕсли;

Проанализируем этот код:

  1. Условие Если Не ИспользуетсяОграничениеПоСкладу Тогда является ключевым. Оно означает, что отбор по полю ДополнительнаяЗапись будет установлен только в том случае, если для текущего пользователя не используется ограничение прав доступа по складу.
  2. Если это условие выполняется, то функция
    
    ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(... "ДополнительнаяЗапись", Ложь ...)
    
    добавляет отбор в динамический список. Этот отбор устанавливает ДополнительнаяЗапись = Ложь, эффективно скрывая все дополнительные записи и оставляя только основные.

Таким образом, мы выясняем истинную причину: если у пользователя есть ограничения прав доступа по складам (то есть, ИспользуетсяОграничениеПоСкладу равно Истина), то система не устанавливает автоматический отбор по ДополнительнаяЗапись = Ложь. В результате динамический список отображает обе записи — основную и дополнительную — что приводит к наблюдаемому дублированию.

Почему так реализовано? Разработчики 1С, вероятно, предполагали, что пользователи с ограничениями по складу должны видеть максимально полную информацию о документах, к которым они имеют доступ, включая аспекты как отправителя, так и получателя. Однако на практике это чаще всего воспринимается как ошибка и вызывает недопонимание.

Решение проблемы: Установка отбора по полю "ДополнительнаяЗапись"

Теперь, когда мы понимаем причину дублирования, мы можем предложить несколько способов решения. Самый простой и безопасный способ — это установка соответствующего отбора для пользователя.

1. Пользовательская настройка отбора в динамическом списке

Это наиболее предпочтительный метод, так как он не требует изменения конфигурации и может быть выполнен непосредственно пользователем или администратором системы:

  1. Откройте журнал "Внутренние документы" в режиме 1С:Предприятие.
  2. Нажмите кнопку "Еще" (или аналогичную, в зависимости от интерфейса) и выберите пункт "Настроить список..." или "Изменить форму...".
  3. В открывшемся окне настроек списка перейдите на вкладку "Отбор".
  4. Нажмите кнопку "Добавить новый элемент отбора" (обычно это зеленая кнопка с плюсом).
  5. В поле "Поле" выберите значение "Дополнительная запись".
  6. В поле "Вид сравнения" установите "Равно".
  7. В поле "Значение" установите флажок (или выберите) "Нет" или "Ложь".
  8. Нажмите "Завершить редактирование" или "ОК", чтобы применить настройки.
  9. Сохраните эти настройки как пользовательский вариант списка, чтобы они применялись автоматически при следующем открытии журнала.

После применения этого отбора список документов будет отображать только основные записи, и дубликаты исчезнут.

2. Программное изменение (для разработчиков, с осторожностью)

Если требуется, чтобы данный отбор применялся для всех пользователей с ограничениями по складу без необходимости ручной настройки, можно рассмотреть модификацию кода конфигурации. Однако этот подход требует осторожности и обычно реализуется через механизм расширений, чтобы избежать снятия конфигурации с поддержки.

Мы можем создать расширение, которое будет дополнять или переопределять процедуру УстановитьОтборыДинамическихСписков() для формы списка. В рамках этого расширения мы можем явно установить отбор по ДополнительнаяЗапись = Ложь вне зависимости от условия ИспользуетсяОграничениеПоСкладу.

Пример (концептуальный, требует адаптации под конкретную форму и версию):


// В расширении, в модуле формы списка, после вызова типовой процедуры или
// при переопределении УстановитьОтборыДинамическихСписков()
&НаСервере
Процедура УстановитьОтборыДинамическихСписковНаСервере_Расширение()

    // Вызываем типовую процедуру, если это дополнение
    // Или полностью реализуем логику, если переопределяем
    // ...

    // Принудительно устанавливаем отбор для всех, кто видит дубли
    // Можно добавить условие для конкретных пользователей или ролей, если требуется
    ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(СписокДокументыВнутреннегоТовародвижения, "ДополнительнаяЗапись",
        Ложь, ВидСравненияКомпоновкиДанных.Равно);

КонецПроцедуры

Важно: Любые изменения в коде должны быть тщательно протестированы, чтобы убедиться, что они не нарушают функциональность для других пользователей или ролей, для которых отображение дополнительных записей может быть важным.

Заключение и рекомендации

Проблема дублирования документов в списке "Внутренние документы" в 1С:УТ 11.5, особенно при наличии ограничений прав доступа по складам, является следствием архитектурного решения по хранению данных в РегистрСведений.РеестрДокументов (с использованием поля ДополнительнаяЗапись) и специфики установки отборов в динамических списках. Система 1С, по умолчанию, может не применять фильтр по ДополнительнаяЗапись = Ложь для пользователей с ограничениями по складу, что приводит к отображению как основных, так и дополнительных записей.

Наиболее простое и безопасное решение — это ручная установка пользовательского отбора в динамическом списке, где для поля ДополнительнаяЗапись устанавливается значение Ложь. Для системных администраторов или разработчиков возможно создание расширения, которое автоматизирует этот процесс, но это требует дополнительного тестирования.

Мы всегда рекомендуем сначала использовать стандартные средства настройки интерфейса 1С. Только в случае, если пользовательские настройки не решают проблему или требуется универсальное решение для большой группы пользователей, стоит рассматривать программные модификации.

← На главную